From d30c8d2031259d6dc360f8c96d362bb36665c99c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 19 Jun 2018 10:18:56 +0200 Subject: leds: ledtrig-activity: use ktime_get_boot_ns() get_monotonic_boottime() is deprecated, so let's convert this to the simpler ktime_get_boot_ns(). Signed-off-by: Arnd Bergmann Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-activity.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-activity.c b/drivers/leds/trigger/ledtrig-activity.c index 5081894082bd..6c6f8a9b8d9a 100644 --- a/drivers/leds/trigger/ledtrig-activity.c +++ b/drivers/leds/trigger/ledtrig-activity.c @@ -37,7 +37,6 @@ static void led_activity_function(struct timer_list *t) struct activity_data *activity_data = from_timer(activity_data, t, timer); struct led_classdev *led_cdev = activity_data->led_cdev; - struct timespec boot_time; unsigned int target; unsigned int usage; int delay; @@ -57,8 +56,6 @@ static void led_activity_function(struct timer_list *t) return; } - get_monotonic_boottime(&boot_time); - cpus = 0; curr_used = 0; @@ -76,7 +73,7 @@ static void led_activity_function(struct timer_list *t) * down to 16us, ensuring we won't overflow 32-bit computations below * even up to 3k CPUs, while keeping divides cheap on smaller systems. */ - curr_boot = timespec_to_ns(&boot_time) * cpus; + curr_boot = ktime_get_boot_ns() * cpus; diff_boot = (curr_boot - activity_data->last_boot) >> 16; diff_used = (curr_used - activity_data->last_used) >> 16; activity_data->last_boot = curr_boot; -- cgit v1.2.3 From 8cb21086cc6359c6d4f003a788050308afb211ad Mon Sep 17 00:00:00 2001 From: "Raffaello D. Di Napoli" Date: Mon, 25 Jun 2018 08:50:02 -0400 Subject: leds: Modify PC Engines apu/apu2 driver to support apu3 PC Engines apu3 is an improved version of the apu2, using the same SoC and almost everything else. This patch reuses as much as possible from the apu2 definitions, to avoid redundancy. Signed-off-by: Raffaello D. Di Napoli Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/Kconfig | 5 +++-- drivers/leds/leds-apu.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6e3a998f3370..44097a3e0fcc 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -57,12 +57,13 @@ config LEDS_AAT1290 depends on PINCTRL help This option enables support for the LEDs on the AAT1290. + config LEDS_APU - tristate "Front panel LED support for PC Engines APU/APU2 boards" + tristate "Front panel LED support for PC Engines APU/APU2/APU3 boards" depends on LEDS_CLASS depends on X86 && DMI help - This driver makes the PC Engines APU/APU2 front panel LEDs + This driver makes the PC Engines APU/APU2/APU3 front panel LEDs accessible from userspace programs through the LED subsystem. To compile this driver as a module, choose M here: the diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index 8c93d68964c7..8d42e46e2de3 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -102,6 +102,13 @@ static const struct apu_led_profile apu2_led_profile[] = { { "apu2:green:3", LED_OFF, APU2_FCH_GPIO_BASE + 70 * APU2_IOSIZE }, }; +/* Same as apu2_led_profile, but with "3" in the LED names. */ +static const struct apu_led_profile apu3_led_profile[] = { + { "apu3:green:1", LED_ON, APU2_FCH_GPIO_BASE + 68 * APU2_IOSIZE }, + { "apu3:green:2", LED_OFF, APU2_FCH_GPIO_BASE + 69 * APU2_IOSIZE }, + { "apu3:green:3", LED_OFF, APU2_FCH_GPIO_BASE + 70 * APU2_IOSIZE }, +}; + static const struct dmi_system_id apu_led_dmi_table[] __initconst = { { .ident = "apu", @@ -134,6 +141,30 @@ static const struct dmi_system_id apu_led_dmi_table[] __initconst = { DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu2") } }, + /* PC Engines APU3 with "Legacy" bios < 4.0.8 */ + { + .ident = "apu3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), + DMI_MATCH(DMI_BOARD_NAME, "APU3") + } + }, + /* PC Engines APU3 with "Legacy" bios >= 4.0.8 */ + { + .ident = "apu3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), + DMI_MATCH(DMI_BOARD_NAME, "apu3") + } + }, + /* PC Engines APU2 with "Mainline" bios */ + { + .ident = "apu3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), + DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu3") + } + }, {} }; MODULE_DEVICE_TABLE(dmi, apu_led_dmi_table); @@ -235,6 +266,14 @@ static int __init apu_led_probe(struct platform_device *pdev) apu_led->platform = APU2_LED_PLATFORM; apu_led->num_led_instances = ARRAY_SIZE(apu2_led_profile); apu_led->iosize = APU2_IOSIZE; + } else if (dmi_match(DMI_BOARD_NAME, "APU3") || + dmi_match(DMI_BOARD_NAME, "apu3") || + dmi_match(DMI_BOARD_NAME, "PC Engines apu3")) { + apu_led->profile = apu3_led_profile; + /* Otherwise identical to APU2. */ + apu_led->platform = APU2_LED_PLATFORM; + apu_led->num_led_instances = ARRAY_SIZE(apu3_led_profile); + apu_led->iosize = APU2_IOSIZE; } spin_lock_init(&apu_led->lock); @@ -259,7 +298,10 @@ static int __init apu_led_init(void) if (!(dmi_match(DMI_PRODUCT_NAME, "APU") || dmi_match(DMI_PRODUCT_NAME, "APU2") || dmi_match(DMI_PRODUCT_NAME, "apu2") || - dmi_match(DMI_PRODUCT_NAME, "PC Engines apu2"))) { + dmi_match(DMI_PRODUCT_NAME, "PC Engines apu2") || + dmi_match(DMI_PRODUCT_NAME, "APU3") || + dmi_match(DMI_PRODUCT_NAME, "apu3") || + dmi_match(DMI_PRODUCT_NAME, "PC Engines apu3"))) { pr_err("Unknown PC Engines board: %s\n", dmi_get_system_info(DMI_PRODUCT_NAME)); return -ENODEV; -- cgit v1.2.3 From 3d74243db89f9c7cea7afc471f67e15b96cc6278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 26 Jun 2018 11:37:58 +0200 Subject: leds: triggers: don't depend on LEDS_TRIGGERS twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the triggers are defined in a big if LEDS_TRIGGERS...endif block. So there is no need to let each driver depend on LEDS_TRIGGERS explicitly once more. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/Kconfig | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index a2559b4fdfff..4018af769969 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -10,7 +10,6 @@ if LEDS_TRIGGERS config LEDS_TRIGGER_TIMER tristate "LED Timer Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by a programmable timer via sysfs. Some LED hardware can be programmed to start @@ -21,7 +20,6 @@ config LEDS_TRIGGER_TIMER config LEDS_TRIGGER_ONESHOT tristate "LED One-shot Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to blink in one-shot pulses with parameters controlled via sysfs. It's useful to notify the user on @@ -36,7 +34,6 @@ config LEDS_TRIGGER_ONESHOT config LEDS_TRIGGER_DISK bool "LED Disk Trigger" depends on IDE_GD_ATA || ATA - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by disk activity. If unsure, say Y. @@ -44,14 +41,12 @@ config LEDS_TRIGGER_DISK config LEDS_TRIGGER_MTD bool "LED MTD (NAND/NOR) Trigger" depends on MTD - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by MTD activity. If unsure, say N. config LEDS_TRIGGER_HEARTBEAT tristate "LED Heartbeat Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by a CPU load average. The flash frequency is a hyperbolic function of the 1-minute @@ -60,7 +55,6 @@ config LEDS_TRIGGER_HEARTBEAT config LEDS_TRIGGER_BACKLIGHT tristate "LED backlight Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled as a backlight device: they turn off and on when the display is blanked and unblanked. @@ -69,7 +63,6 @@ config LEDS_TRIGGER_BACKLIGHT config LEDS_TRIGGER_CPU bool "LED CPU Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by active CPUs. This shows the active CPUs across an array of LEDs so you can see which @@ -79,7 +72,6 @@ config LEDS_TRIGGER_CPU config LEDS_TRIGGER_ACTIVITY tristate "LED activity Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by an immediate CPU usage. The flash frequency and duty cycle varies from faint flashes to @@ -88,7 +80,6 @@ config LEDS_TRIGGER_ACTIVITY config LEDS_TRIGGER_GPIO tristate "LED GPIO Trigger" - depends on LEDS_TRIGGERS depends on GPIOLIB || COMPILE_TEST help This allows LEDs to be controlled by gpio events. It's good @@ -101,7 +92,6 @@ config LEDS_TRIGGER_GPIO config LEDS_TRIGGER_DEFAULT_ON tristate "LED Default ON Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be initialised in the ON state. If unsure, say Y. @@ -111,7 +101,6 @@ comment "iptables trigger is under Netfilter config (LED target)" config LEDS_TRIGGER_TRANSIENT tristate "LED Transient Trigger" - depends on LEDS_TRIGGERS help This allows one time activation of a transient state on GPIO/PWM based hardware. @@ -119,7 +108,6 @@ config LEDS_TRIGGER_TRANSIENT config LEDS_TRIGGER_CAMERA tristate "LED Camera Flash/Torch Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled as a camera flash/torch device. This enables direct flash/torch on/off by the driver, kernel space. @@ -127,7 +115,6 @@ config LEDS_TRIGGER_CAMERA config LEDS_TRIGGER_PANIC bool "LED Panic Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be configured to blink on a kernel panic. Enabling this option will allow to mark certain LEDs as panic indicators, @@ -137,7 +124,7 @@ config LEDS_TRIGGER_PANIC config LEDS_TRIGGER_NETDEV tristate "LED Netdev Trigger" - depends on NET && LEDS_TRIGGERS + depends on NET help This allows LEDs to be controlled by network device activity. If unsure, say Y. -- cgit v1.2.3 From 868ec1cad0d93365ddbb1cba2b671c6c8c9221ba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Jun 2018 06:49:06 -0300 Subject: devicectree: bindings: fix location of leds common file The leds.txt was moved and renamed. Fix references to it accordingly. Fixes: f67605394f0b ("devicetree/bindings: Move gpio-leds binding into leds directory") Signed-off-by: Mauro Carvalho Chehab Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- Documentation/devicetree/bindings/leds/common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt index 1d4afe9644b6..aa1399814a2a 100644 --- a/Documentation/devicetree/bindings/leds/common.txt +++ b/Documentation/devicetree/bindings/leds/common.txt @@ -31,7 +31,7 @@ Optional properties for child nodes: "backlight" - LED will act as a back-light, controlled by the framebuffer system "default-on" - LED will turn on (but for leds-gpio see "default-state" - property in Documentation/devicetree/bindings/gpio/led.txt) + property in Documentation/devicetree/bindings/leds/leds-gpio.txt) "heartbeat" - LED "double" flashes at a load average based rate "disk-activity" - LED indicates disk activity "ide-disk" - LED indicates IDE disk activity (deprecated), -- cgit v1.2.3 From 30f3b42147ba6f29bc95c1bba34468740762d91b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Jun 2018 11:20:52 +0200 Subject: can: mark led trigger as broken MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver was suggested for deletion as it implements a subset of the netdev trigger. It's in the way for further cleanups in the trigger code but doesn't get an Ack by someone who can actually test and confirm that the netdev trigger works for can devices. So marking as broken to get forward with the cleanups. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/net/can/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 2cb75988b328..7cdd0cead693 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -73,6 +73,12 @@ config CAN_CALC_BITTIMING config CAN_LEDS bool "Enable LED triggers for Netlink based drivers" depends on LEDS_CLASS + # The netdev trigger (LEDS_TRIGGER_NETDEV) should be able to do + # everything that this driver is doing. This is marked as broken + # because it uses stuff that is intended to be changed or removed. + # Please consider switching to the netdev trigger and confirm it + # fulfills your needs instead of fixing this driver. + depends on BROKEN select LEDS_TRIGGERS ---help--- This option adds two LED triggers for packet receive and transmit -- cgit v1.2.3 From f041f96abcf8718540e94aac6e73604c5d33d9f9 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 27 Jun 2018 20:52:33 +0200 Subject: dt-bindings: leds: Add bindings for lltc,lt3593 This patch adds the bindings document for LT3593 LED drivers. The binding is kept consistent with other LED driver bindings in that it stores all the LED-specific properties in its own subnode. As the hardware only supports one channel, there can consequently only be one sub-node. Signed-off-by: Daniel Mack Reviewed-by: Rob Herring Signed-off-by: Jacek Anaszewski --- .../devicetree/bindings/leds/leds-lt3593.txt | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/leds-lt3593.txt diff --git a/Documentation/devicetree/bindings/leds/leds-lt3593.txt b/Documentation/devicetree/bindings/leds/leds-lt3593.txt new file mode 100644 index 000000000000..6b2cabc36c0c --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-lt3593.txt @@ -0,0 +1,32 @@ +Bindings for Linear Technologies LT3593 LED controller + +Required properties: +- compatible: Should be "lltc,lt3593". +- lltc,ctrl-gpios: A handle to the GPIO that is connected to the 'CTRL' + pin of the chip. + +The hardware supports only one LED. The properties of this LED are +configured in a sub-node in the device node. + +Optional sub-node properties: +- label: A label for the LED. If none is given, the LED will be + named "lt3595::". +- linux,default-trigger: The default trigger for the LED. + See Documentation/devicetree/bindings/leds/common.txt +- default-state: The initial state of the LED. + See Documentation/devicetree/bindings/leds/common.txt + +If multiple chips of this type are found in a design, each one needs to +be handled by its own device node. + +Example: + +led-controller { + compatible = "lltc,lt3593"; + lltc,ctrl-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; + + led { + label = "white:backlight"; + default-state = "on"; + }; +}; -- cgit v1.2.3 From d8be286739d6317b2c4b2a6c2cbf63d76410ff90 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 27 Jun 2018 20:52:34 +0200 Subject: leds: lt3593: merge functions and clean up code In preparation to DT probe functionality, merge create_lt3593_led() into its only call-site. The DT based setup code will be quite different, so this internal helper function is of no help. This also changes the way the driver works by only handling one entry inside 'struct gpio_led_platform_data'. If multiple devices of the same type are found in a design, there should be a platform device for each of them. The only mainline user of this driver is not affected by this change. Last, use devm_led_classdev_register() instead of led_classdev_register(), so the driver's remove callback can go away. Signed-off-by: Daniel Mack Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lt3593.c | 103 +++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 68 deletions(-) diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 5ec730a31b65..1a3dc347db21 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -71,104 +71,71 @@ static int lt3593_led_set(struct led_classdev *led_cdev, return 0; } -static int create_lt3593_led(const struct gpio_led *template, - struct lt3593_led_data *led_dat, struct device *parent) +static struct lt3593_led_data *lt3593_led_probe_pdata(struct device *dev) { + struct gpio_led_platform_data *pdata = dev_get_platdata(dev); + const struct gpio_led *template = &pdata->leds[0]; + struct lt3593_led_data *led_data; int ret, state; - /* skip leds on GPIOs that aren't available */ + if (pdata->num_leds != 1) + return ERR_PTR(-EINVAL); + + led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL); + if (!led_data) + return ERR_PTR(-ENOMEM); + if (!gpio_is_valid(template->gpio)) { - dev_info(parent, "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n", - KBUILD_MODNAME, template->gpio, template->name); - return 0; + dev_info(dev, "skipping unavailable LT3593 LED at gpio " + "%d (%s)\n", template->gpio, template->name); + return ERR_PTR(-EINVAL); } - led_dat->cdev.name = template->name; - led_dat->cdev.default_trigger = template->default_trigger; - led_dat->gpio = template->gpio; - - led_dat->cdev.brightness_set_blocking = lt3593_led_set; + led_data->cdev.name = template->name; + led_data->cdev.default_trigger = template->default_trigger; + led_data->gpio = template->gpio; + led_data->cdev.brightness_set_blocking = lt3593_led_set; state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); - led_dat->cdev.brightness = state ? LED_FULL : LED_OFF; + led_data->cdev.brightness = state ? LED_FULL : LED_OFF; if (!template->retain_state_suspended) - led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; + led_data->cdev.flags |= LED_CORE_SUSPENDRESUME; - ret = devm_gpio_request_one(parent, template->gpio, state ? + ret = devm_gpio_request_one(dev, template->gpio, state ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, template->name); if (ret < 0) - return ret; + return ERR_PTR(ret); - ret = led_classdev_register(parent, &led_dat->cdev); + ret = devm_led_classdev_register(dev, &led_data->cdev); if (ret < 0) - return ret; - - dev_info(parent, "%s: registered LT3593 LED '%s' at GPIO %d\n", - KBUILD_MODNAME, template->name, template->gpio); + return ERR_PTR(ret); - return 0; -} + dev_info(dev, "registered LT3593 LED '%s' at GPIO %d\n", + template->name, template->gpio); -static void delete_lt3593_led(struct lt3593_led_data *led) -{ - if (!gpio_is_valid(led->gpio)) - return; - - led_classdev_unregister(&led->cdev); + return led_data; } static int lt3593_led_probe(struct platform_device *pdev) { - struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct lt3593_led_data *leds_data; - int i, ret = 0; - - if (!pdata) - return -EBUSY; - - leds_data = devm_kcalloc(&pdev->dev, - pdata->num_leds, sizeof(struct lt3593_led_data), - GFP_KERNEL); - if (!leds_data) - return -ENOMEM; - - for (i = 0; i < pdata->num_leds; i++) { - ret = create_lt3593_led(&pdata->leds[i], &leds_data[i], - &pdev->dev); - if (ret < 0) - goto err; - } + struct device *dev = &pdev->dev; + struct lt3593_led_data *led_data; - platform_set_drvdata(pdev, leds_data); - - return 0; - -err: - for (i = i - 1; i >= 0; i--) - delete_lt3593_led(&leds_data[i]); - - return ret; -} - -static int lt3593_led_remove(struct platform_device *pdev) -{ - int i; - struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct lt3593_led_data *leds_data; - - leds_data = platform_get_drvdata(pdev); + if (dev_get_platdata(dev)) { + led_data = lt3593_led_probe_pdata(dev); + if (IS_ERR(led_data)) + return PTR_ERR(led_data); + } - for (i = 0; i < pdata->num_leds; i++) - delete_lt3593_led(&leds_data[i]); + platform_set_drvdata(pdev, led_data); return 0; } static struct platform_driver lt3593_led_driver = { .probe = lt3593_led_probe, - .remove = lt3593_led_remove, .driver = { .name = "leds-lt3593", }, -- cgit v1.2.3 From 73f103c9528135bc896459a58e2371ce86090aea Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 27 Jun 2018 20:52:35 +0200 Subject: leds: lt3593: switch to gpiod interface Clean up the code a bit and transition over to the gpiod based interface. Signed-off-by: Daniel Mack Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lt3593.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 1a3dc347db21..a096ee64cbbb 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -21,12 +21,13 @@ #include #include #include +#include #include #include struct lt3593_led_data { struct led_classdev cdev; - unsigned gpio; + struct gpio_desc *gpiod; }; static int lt3593_led_set(struct led_classdev *led_cdev, @@ -46,25 +47,25 @@ static int lt3593_led_set(struct led_classdev *led_cdev, */ if (value == 0) { - gpio_set_value_cansleep(led_dat->gpio, 0); + gpiod_set_value_cansleep(led_dat->gpiod, 0); return 0; } pulses = 32 - (value * 32) / 255; if (pulses == 0) { - gpio_set_value_cansleep(led_dat->gpio, 0); + gpiod_set_value_cansleep(led_dat->gpiod, 0); mdelay(1); - gpio_set_value_cansleep(led_dat->gpio, 1); + gpiod_set_value_cansleep(led_dat->gpiod, 1); return 0; } - gpio_set_value_cansleep(led_dat->gpio, 1); + gpiod_set_value_cansleep(led_dat->gpiod, 1); while (pulses--) { - gpio_set_value_cansleep(led_dat->gpio, 0); + gpiod_set_value_cansleep(led_dat->gpiod, 0); udelay(1); - gpio_set_value_cansleep(led_dat->gpio, 1); + gpiod_set_value_cansleep(led_dat->gpiod, 1); udelay(1); } @@ -85,15 +86,8 @@ static struct lt3593_led_data *lt3593_led_probe_pdata(struct device *dev) if (!led_data) return ERR_PTR(-ENOMEM); - if (!gpio_is_valid(template->gpio)) { - dev_info(dev, "skipping unavailable LT3593 LED at gpio " - "%d (%s)\n", template->gpio, template->name); - return ERR_PTR(-EINVAL); - } - led_data->cdev.name = template->name; led_data->cdev.default_trigger = template->default_trigger; - led_data->gpio = template->gpio; led_data->cdev.brightness_set_blocking = lt3593_led_set; state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); @@ -108,6 +102,10 @@ static struct lt3593_led_data *lt3593_led_probe_pdata(struct device *dev) if (ret < 0) return ERR_PTR(ret); + led_data->gpiod = gpio_to_desc(template->gpio); + if (!led_data->gpiod) + return ERR_PTR(-EPROBE_DEFER); + ret = devm_led_classdev_register(dev, &led_data->cdev); if (ret < 0) return ERR_PTR(ret); -- cgit v1.2.3 From 8cd7d6daba9330383259686d1cc1d64caf857b11 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 27 Jun 2018 20:52:36 +0200 Subject: leds: lt3593: Add device tree probing glue The binding details are described in an earlier commit that adds the documentation. Signed-off-by: Daniel Mack Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lt3593.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index a096ee64cbbb..2e35a4a4c571 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -24,8 +24,11 @@ #include #include #include +#include +#include struct lt3593_led_data { + char name[LED_MAX_NAME_SIZE]; struct led_classdev cdev; struct gpio_desc *gpiod; }; @@ -120,22 +123,89 @@ static int lt3593_led_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct lt3593_led_data *led_data; + struct fwnode_handle *child; + int ret, state = LEDS_GPIO_DEFSTATE_OFF; + enum gpiod_flags flags = GPIOD_OUT_LOW; + const char *tmp; if (dev_get_platdata(dev)) { led_data = lt3593_led_probe_pdata(dev); if (IS_ERR(led_data)) return PTR_ERR(led_data); + + goto out; } + if (!dev->of_node) + return -ENODEV; + + led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL); + if (!led_data) + return -ENOMEM; + + if (device_get_child_node_count(dev) != 1) { + dev_err(dev, "Device must have exactly one LED sub-node."); + return -EINVAL; + } + + led_data->gpiod = devm_gpiod_get(dev, "lltc,ctrl", 0); + if (IS_ERR(led_data->gpiod)) + return PTR_ERR(led_data->gpiod); + + child = device_get_next_child_node(dev, NULL); + + ret = fwnode_property_read_string(child, "label", &tmp); + if (ret < 0) + snprintf(led_data->name, sizeof(led_data->name), + "lt3593::"); + else + snprintf(led_data->name, sizeof(led_data->name), + "lt3593:%s", tmp); + + fwnode_property_read_string(child, "linux,default-trigger", + &led_data->cdev.default_trigger); + + if (!fwnode_property_read_string(child, "default-state", &tmp)) { + if (!strcmp(tmp, "keep")) { + state = LEDS_GPIO_DEFSTATE_KEEP; + flags = GPIOD_ASIS; + } else if (!strcmp(tmp, "on")) { + state = LEDS_GPIO_DEFSTATE_ON; + flags = GPIOD_OUT_HIGH; + } + } + + led_data->cdev.name = led_data->name; + led_data->cdev.brightness_set_blocking = lt3593_led_set; + led_data->cdev.brightness = state ? LED_FULL : LED_OFF; + + ret = devm_led_classdev_register(dev, &led_data->cdev); + if (ret < 0) { + fwnode_handle_put(child); + return ret; + } + + led_data->cdev.dev->of_node = dev->of_node; + +out: platform_set_drvdata(pdev, led_data); return 0; } +#ifdef CONFIG_OF +static const struct of_device_id of_lt3593_leds_match[] = { + { .compatible = "lltc,lt3593", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_lt3593_leds_match); +#endif + static struct platform_driver lt3593_led_driver = { .probe = lt3593_led_probe, .driver = { .name = "leds-lt3593", + .of_match_table = of_match_ptr(of_lt3593_leds_match), }, }; -- cgit v1.2.3 From dd08ac2e5fbc867c5793c3fc0404ef16390b5206 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 27 Jun 2018 20:52:37 +0200 Subject: leds: lt3593: update email address and switch to SPDX license header Update the email address in the module information and in the comments and in the module information, and drop the existing boilerplate in favor of a SPDX header. Also sync the module license information with the header. Signed-off-by: Daniel Mack Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lt3593.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 2e35a4a4c571..de3623e0d094 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -1,20 +1,5 @@ -/* - * LEDs driver for LT3593 controllers - * - * See the datasheet at http://cds.linear.com/docs/Datasheet/3593f.pdf - * - * Copyright (c) 2009 Daniel Mack - * - * Based on leds-gpio.c, - * - * Copyright (C) 2007 8D Technologies inc. - * Raphael Assenat - * Copyright (C) 2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2009,2018 Daniel Mack #include #include @@ -211,7 +196,7 @@ static struct platform_driver lt3593_led_driver = { module_platform_driver(lt3593_led_driver); -MODULE_AUTHOR("Daniel Mack "); +MODULE_AUTHOR("Daniel Mack "); MODULE_DESCRIPTION("LED driver for LT3593 controllers"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:leds-lt3593"); -- cgit v1.2.3 From 7a5de56db902ea632a0ff0c2b47481d278db645f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 2 Jul 2018 17:50:37 +0100 Subject: leds: max8997: use mode when calling max8997_led_set_mode Variable mode is assigned to pdata->led_pdata->mode[led->id] and yet is not being used when calling function max8997_led_set_mode. Fix this by using mode when calling max8997_led_set_mode. Cleans up clang warning: warning: variable 'mode' set but not used [-Wunused-but-set-variable] Fixes: 8584cb82f151 ("leds: Add suuport for MAX8997-LED driver") Signed-off-by: Colin Ian King Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max8997.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c index 4edf74f1d6d4..8c019c28f9f5 100644 --- a/drivers/leds/leds-max8997.c +++ b/drivers/leds/leds-max8997.c @@ -268,7 +268,7 @@ static int max8997_led_probe(struct platform_device *pdev) mode = pdata->led_pdata->mode[led->id]; brightness = pdata->led_pdata->brightness[led->id]; - max8997_led_set_mode(led, pdata->led_pdata->mode[led->id]); + max8997_led_set_mode(led, mode); if (brightness > led->cdev.max_brightness) brightness = led->cdev.max_brightness; -- cgit v1.2.3 From 43d20ff3633112322de38c18b4b35bbbf04438d7 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 2 Jul 2018 13:12:13 -0500 Subject: leds: lm3692x: Update license header to SPDX Update the license header to the current SPDX licensing format. Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3692x.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index 437173d1712c..e518ae36f410 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -1,17 +1,6 @@ -/* - * TI lm3692x LED Driver - * - * Copyright (C) 2017 Texas Instruments - * - * Author: Dan Murphy - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Data sheet is located - * http://www.ti.com/lit/ds/snvsa29/snvsa29.pdf - */ +// SPDX-License-Identifier: GPL-2.0 +// TI LM3692x LED chip family driver +// Copyright (C) 2017-18 Texas Instruments Incorporated - http://www.ti.com/ #include #include -- cgit v1.2.3 From 9a5c1c64ac0a4d01c78328283dac7a9dc33ff0f9 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 2 Jul 2018 13:12:14 -0500 Subject: leds: lm3692x: Change DT calls to fwnode calls Update the code to use the fwnode calls as opposed to ARM DT node api's. This allows the device to be used with either DT configurations or ACPI definitions. Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3692x.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index e518ae36f410..9e6432b6a3b5 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -267,30 +267,15 @@ out: static int lm3692x_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int ret; + struct fwnode_handle *child = NULL; struct lm3692x_led *led; - struct device_node *np = client->dev.of_node; - struct device_node *child_node; const char *name; + int ret; led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; - for_each_available_child_of_node(np, child_node) { - led->led_dev.default_trigger = of_get_property(child_node, - "linux,default-trigger", - NULL); - - ret = of_property_read_string(child_node, "label", &name); - if (!ret) - snprintf(led->label, sizeof(led->label), - "%s:%s", id->name, name); - else - snprintf(led->label, sizeof(led->label), - "%s::backlight_cluster", id->name); - }; - led->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(led->enable_gpio)) { @@ -323,6 +308,25 @@ static int lm3692x_probe(struct i2c_client *client, if (ret) return ret; + child = device_get_next_child_node(&led->client->dev, child); + if (!child) { + dev_err(&led->client->dev, "No LED Child node\n"); + return ret; + } + + fwnode_property_read_string(child, "linux,default-trigger", + &led->led_dev.default_trigger); + + ret = fwnode_property_read_string(child, "label", &name); + if (ret) + snprintf(led->label, sizeof(led->label), + "%s::", led->client->name); + else + snprintf(led->label, sizeof(led->label), + "%s:%s", led->client->name, name); + + led->led_dev.dev->of_node = to_of_node(child); + ret = devm_led_classdev_register(&client->dev, &led->led_dev); if (ret) { dev_err(&client->dev, "led register err: %d\n", ret); -- cgit v1.2.3 From 581e3ca38a1aa40b742baad39026f440445488d4 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 2 Jul 2018 13:12:15 -0500 Subject: dt: bindings: lm3692x: Update binding for LED sync control Update the binding to be able to configure the LED sync to turn on. The LM36922 has one output but can sync current to 2 LED strings. The user may only use one sync so the other syncs need to be disabled. The LM36923 has 3 LED syncs. Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- Documentation/devicetree/bindings/leds/leds-lm3692x.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt index 6c9074f84a51..08b352840bd7 100644 --- a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt +++ b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt @@ -20,7 +20,10 @@ Optional properties: - vled-supply : LED supply Required child properties: - - reg : 0 + - reg : 0 - Will enable all LED sync paths + 1 - Will enable the LED1 sync + 2 - Will enable the LED2 sync + 3 - Will enable the LED3 sync (LM36923 only) Optional child properties: - label : see Documentation/devicetree/bindings/leds/common.txt -- cgit v1.2.3 From 07abd4325e7013c728bf9642fbb862aa9eb4a367 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 2 Jul 2018 13:12:16 -0500 Subject: leds: lm3692x: Support LED sync configuration The LM36922 has one output but can sync current to 2 LED strings. The user may only use one sync so the other syncs need to be disabled. The LM36923 has 3 LED syncs. Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3692x.c | 158 +++++++++++++++++++++++++++++++++----------- 1 file changed, 120 insertions(+), 38 deletions(-) diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index 9e6432b6a3b5..4f413a7c5f05 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -15,6 +15,9 @@ #include #include +#define LM36922_MODEL 0 +#define LM36923_MODEL 1 + #define LM3692X_REV 0x0 #define LM3692X_RESET 0x1 #define LM3692X_EN 0x10 @@ -33,6 +36,9 @@ #define LM3692X_DEVICE_EN BIT(0) #define LM3692X_LED1_EN BIT(1) #define LM3692X_LED2_EN BIT(2) +#define LM36923_LED3_EN BIT(3) +#define LM3692X_ENABLE_MASK (LM3692X_DEVICE_EN | LM3692X_LED1_EN | \ + LM3692X_LED2_EN | LM36923_LED3_EN) /* Brightness Control Bits */ #define LM3692X_BL_ADJ_POL BIT(0) @@ -98,6 +104,8 @@ * @enable_gpio - VDDIO/EN gpio to enable communication interface * @regulator - LED supply regulator pointer * @label - LED label + * @led_enable - LED sync to be enabled + * @model_id - Current device model ID enumerated */ struct lm3692x_led { struct mutex lock; @@ -107,6 +115,8 @@ struct lm3692x_led { struct gpio_desc *enable_gpio; struct regulator *regulator; char label[LED_MAX_NAME_SIZE]; + int led_enable; + int model_id; }; static const struct reg_default lm3692x_reg_defs[] = { @@ -189,6 +199,7 @@ out: static int lm3692x_init(struct lm3692x_led *led) { + int enable_state; int ret; if (led->regulator) { @@ -215,9 +226,25 @@ static int lm3692x_init(struct lm3692x_led *led) /* * For glitch free operation, the following data should - * only be written while device enable bit is 0 + * only be written while LEDx enable bits are 0 and the device enable + * bit is set to 1. * per Section 7.5.14 of the data sheet */ + ret = regmap_write(led->regmap, LM3692X_EN, LM3692X_DEVICE_EN); + if (ret) + goto out; + + /* Set the brightness to 0 so when enabled the LEDs do not come + * on with full brightness. + */ + ret = regmap_write(led->regmap, LM3692X_BRT_MSB, 0); + if (ret) + goto out; + + ret = regmap_write(led->regmap, LM3692X_BRT_LSB, 0); + if (ret) + goto out; + ret = regmap_write(led->regmap, LM3692X_PWM_CTRL, LM3692X_PWM_FILTER_100 | LM3692X_PWM_SAMP_24MHZ); if (ret) @@ -247,6 +274,38 @@ static int lm3692x_init(struct lm3692x_led *led) if (ret) goto out; + switch (led->led_enable) { + case 0: + default: + if (led->model_id == LM36923_MODEL) + enable_state = LM3692X_LED1_EN | LM3692X_LED2_EN | + LM36923_LED3_EN; + else + enable_state = LM3692X_LED1_EN | LM3692X_LED2_EN; + + break; + case 1: + enable_state = LM3692X_LED1_EN; + break; + case 2: + enable_state = LM3692X_LED2_EN; + break; + + case 3: + if (led->model_id == LM36923_MODEL) { + enable_state = LM36923_LED3_EN; + break; + } + + ret = -EINVAL; + dev_err(&led->client->dev, + "LED3 sync not available on this device\n"); + goto out; + } + + ret = regmap_update_bits(led->regmap, LM3692X_EN, LM3692X_ENABLE_MASK, + enable_state | LM3692X_DEVICE_EN); + return ret; out: dev_err(&led->client->dev, "Fail writing initialization values\n"); @@ -263,55 +322,29 @@ out: return ret; } - -static int lm3692x_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int lm3692x_probe_dt(struct lm3692x_led *led) { struct fwnode_handle *child = NULL; - struct lm3692x_led *led; const char *name; int ret; - led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); - if (!led) - return -ENOMEM; - - led->enable_gpio = devm_gpiod_get_optional(&client->dev, + led->enable_gpio = devm_gpiod_get_optional(&led->client->dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(led->enable_gpio)) { ret = PTR_ERR(led->enable_gpio); - dev_err(&client->dev, "Failed to get enable gpio: %d\n", ret); + dev_err(&led->client->dev, "Failed to get enable gpio: %d\n", + ret); return ret; } - led->regulator = devm_regulator_get(&client->dev, "vled"); + led->regulator = devm_regulator_get(&led->client->dev, "vled"); if (IS_ERR(led->regulator)) led->regulator = NULL; - led->client = client; - led->led_dev.name = led->label; - led->led_dev.brightness_set_blocking = lm3692x_brightness_set; - - mutex_init(&led->lock); - - i2c_set_clientdata(client, led); - - led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config); - if (IS_ERR(led->regmap)) { - ret = PTR_ERR(led->regmap); - dev_err(&client->dev, "Failed to allocate register map: %d\n", - ret); - return ret; - } - - ret = lm3692x_init(led); - if (ret) - return ret; - child = device_get_next_child_node(&led->client->dev, child); if (!child) { dev_err(&led->client->dev, "No LED Child node\n"); - return ret; + return -ENODEV; } fwnode_property_read_string(child, "linux,default-trigger", @@ -325,14 +358,57 @@ static int lm3692x_probe(struct i2c_client *client, snprintf(led->label, sizeof(led->label), "%s:%s", led->client->name, name); - led->led_dev.dev->of_node = to_of_node(child); + ret = fwnode_property_read_u32(child, "reg", &led->led_enable); + if (ret) { + dev_err(&led->client->dev, "reg DT property missing\n"); + return ret; + } + + led->led_dev.name = led->label; - ret = devm_led_classdev_register(&client->dev, &led->led_dev); + ret = devm_led_classdev_register(&led->client->dev, &led->led_dev); if (ret) { - dev_err(&client->dev, "led register err: %d\n", ret); + dev_err(&led->client->dev, "led register err: %d\n", ret); + return ret; + } + + led->led_dev.dev->of_node = to_of_node(child); + + return 0; +} + +static int lm3692x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lm3692x_led *led; + int ret; + + led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); + if (!led) + return -ENOMEM; + + mutex_init(&led->lock); + led->client = client; + led->led_dev.brightness_set_blocking = lm3692x_brightness_set; + led->model_id = id->driver_data; + i2c_set_clientdata(client, led); + + led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config); + if (IS_ERR(led->regmap)) { + ret = PTR_ERR(led->regmap); + dev_err(&client->dev, "Failed to allocate register map: %d\n", + ret); return ret; } + ret = lm3692x_probe_dt(led); + if (ret) + return ret; + + ret = lm3692x_init(led); + if (ret) + return ret; + return 0; } @@ -341,6 +417,12 @@ static int lm3692x_remove(struct i2c_client *client) struct lm3692x_led *led = i2c_get_clientdata(client); int ret; + ret = regmap_update_bits(led->regmap, LM3692X_EN, LM3692X_DEVICE_EN, 0); + if (ret) { + dev_err(&led->client->dev, "Failed to disable regulator\n"); + return ret; + } + if (led->enable_gpio) gpiod_direction_output(led->enable_gpio, 0); @@ -357,8 +439,8 @@ static int lm3692x_remove(struct i2c_client *client) } static const struct i2c_device_id lm3692x_id[] = { - { "lm36922", 0 }, - { "lm36923", 1 }, + { "lm36922", LM36922_MODEL }, + { "lm36923", LM36923_MODEL }, { } }; MODULE_DEVICE_TABLE(i2c, lm3692x_id); -- cgit v1.2.3 From 033692eb3ec8305f6e9998b297aaec6899680637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 2 Jul 2018 22:05:20 +0200 Subject: leds: triggers: make the MODULE_LICENSE string match the actual license MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These files are licensed under GPL version 2 only. So use "GPL v2" instead of "GPL" (which means v2 or later). Also remove an empty (but commented) line at the end of the license header which nicely proves in the context that the drivers are really v2 only :-) Signed-off-by: Uwe Kleine-König Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-activity.c | 4 ++-- drivers/leds/trigger/ledtrig-camera.c | 3 +-- drivers/leds/trigger/ledtrig-default-on.c | 3 +-- drivers/leds/trigger/ledtrig-gpio.c | 3 +-- drivers/leds/trigger/ledtrig-heartbeat.c | 4 ++-- drivers/leds/trigger/ledtrig-timer.c | 3 +-- 6 files changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-activity.c b/drivers/leds/trigger/ledtrig-activity.c index 6c6f8a9b8d9a..b39e1bb9a9ec 100644 --- a/drivers/leds/trigger/ledtrig-activity.c +++ b/drivers/leds/trigger/ledtrig-activity.c @@ -7,8 +7,8 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ + #include #include #include @@ -269,4 +269,4 @@ module_exit(activity_exit); MODULE_AUTHOR("Willy Tarreau "); MODULE_DESCRIPTION("Activity LED trigger"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-camera.c b/drivers/leds/trigger/ledtrig-camera.c index 9bd73a8bad5c..091a09a20c58 100644 --- a/drivers/leds/trigger/ledtrig-camera.c +++ b/drivers/leds/trigger/ledtrig-camera.c @@ -10,7 +10,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ #include @@ -54,4 +53,4 @@ module_exit(ledtrig_camera_exit); MODULE_DESCRIPTION("LED Trigger for Camera Flash/Torch Control"); MODULE_AUTHOR("Milo Kim"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-default-on.c b/drivers/leds/trigger/ledtrig-default-on.c index ff455cb46680..4ccea04b7a6b 100644 --- a/drivers/leds/trigger/ledtrig-default-on.c +++ b/drivers/leds/trigger/ledtrig-default-on.c @@ -8,7 +8,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ #include @@ -42,4 +41,4 @@ module_exit(defon_trig_exit); MODULE_AUTHOR("Nick Forbes "); MODULE_DESCRIPTION("Default-ON LED trigger"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-gpio.c b/drivers/leds/trigger/ledtrig-gpio.c index 8891e88d54dd..93906a17a4b6 100644 --- a/drivers/leds/trigger/ledtrig-gpio.c +++ b/drivers/leds/trigger/ledtrig-gpio.c @@ -6,7 +6,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ #include @@ -235,4 +234,4 @@ module_exit(gpio_trig_exit); MODULE_AUTHOR("Felipe Balbi "); MODULE_DESCRIPTION("GPIO LED trigger"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c index f0896de410b8..304b929edb8e 100644 --- a/drivers/leds/trigger/ledtrig-heartbeat.c +++ b/drivers/leds/trigger/ledtrig-heartbeat.c @@ -9,8 +9,8 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ + #include #include #include @@ -213,4 +213,4 @@ module_exit(heartbeat_trig_exit); MODULE_AUTHOR("Atsushi Nemoto "); MODULE_DESCRIPTION("Heartbeat LED trigger"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-timer.c b/drivers/leds/trigger/ledtrig-timer.c index 8d09327b5719..10fc0966b0e3 100644 --- a/drivers/leds/trigger/ledtrig-timer.c +++ b/drivers/leds/trigger/ledtrig-timer.c @@ -8,7 +8,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ #include @@ -127,4 +126,4 @@ module_exit(timer_trig_exit); MODULE_AUTHOR("Richard Purdie "); MODULE_DESCRIPTION("Timer LED trigger"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 2282e125a406e09331c5a785e3df29035c99a607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 2 Jul 2018 22:05:21 +0200 Subject: leds: triggers: let struct led_trigger::activate() return an error code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given that activating a trigger can fail, let the callback return an indication. This prevents to have a trigger active according to the "trigger" sysfs attribute but not functional. All users are changed accordingly to return 0 for now. There is no intended change in behaviour. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/led-triggers.c | 24 +++++++++++++++++++++--- drivers/leds/trigger/ledtrig-activity.c | 8 +++++--- drivers/leds/trigger/ledtrig-backlight.c | 8 +++++--- drivers/leds/trigger/ledtrig-default-on.c | 3 ++- drivers/leds/trigger/ledtrig-gpio.c | 8 +++++--- drivers/leds/trigger/ledtrig-heartbeat.c | 8 +++++--- drivers/leds/trigger/ledtrig-netdev.c | 8 +++++--- drivers/leds/trigger/ledtrig-oneshot.c | 8 +++++--- drivers/leds/trigger/ledtrig-timer.c | 8 +++++--- drivers/leds/trigger/ledtrig-transient.c | 8 +++++--- drivers/tty/vt/keyboard.c | 4 +++- drivers/usb/core/ledtrig-usbport.c | 7 ++++--- include/linux/leds.h | 14 +++++++++----- net/bluetooth/leds.c | 6 ++++-- net/mac80211/led.c | 20 +++++++++++++++----- net/rfkill/core.c | 4 +++- 16 files changed, 101 insertions(+), 45 deletions(-) diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 431123b048a2..a8786f4b3453 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -103,15 +103,16 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, EXPORT_SYMBOL_GPL(led_trigger_show); /* Caller must ensure led_cdev->trigger_lock held */ -void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) +int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) { unsigned long flags; char *event = NULL; char *envp[2]; const char *name; + int ret; if (!led_cdev->trigger && !trig) - return; + return 0; name = trig ? trig->name : "none"; event = kasprintf(GFP_KERNEL, "TRIGGER=%s", name); @@ -134,8 +135,14 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) list_add_tail(&led_cdev->trig_list, &trig->led_cdevs); write_unlock_irqrestore(&trig->leddev_list_lock, flags); led_cdev->trigger = trig; + if (trig->activate) - trig->activate(led_cdev); + ret = trig->activate(led_cdev); + else + ret = 0; + + if (ret) + goto err_activate; } if (event) { @@ -146,6 +153,17 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) "%s: Error sending uevent\n", __func__); kfree(event); } + + return 0; + +err_activate: + led_cdev->trigger = NULL; + write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); + list_del(&led_cdev->trig_list); + write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); + led_set_brightness(led_cdev, LED_OFF); + + return ret; } EXPORT_SYMBOL_GPL(led_trigger_set); diff --git a/drivers/leds/trigger/ledtrig-activity.c b/drivers/leds/trigger/ledtrig-activity.c index b39e1bb9a9ec..2fc065fb1754 100644 --- a/drivers/leds/trigger/ledtrig-activity.c +++ b/drivers/leds/trigger/ledtrig-activity.c @@ -178,20 +178,20 @@ static ssize_t led_invert_store(struct device *dev, static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); -static void activity_activate(struct led_classdev *led_cdev) +static int activity_activate(struct led_classdev *led_cdev) { struct activity_data *activity_data; int rc; activity_data = kzalloc(sizeof(*activity_data), GFP_KERNEL); if (!activity_data) - return; + return 0; led_cdev->trigger_data = activity_data; rc = device_create_file(led_cdev->dev, &dev_attr_invert); if (rc) { kfree(led_cdev->trigger_data); - return; + return 0; } activity_data->led_cdev = led_cdev; @@ -201,6 +201,8 @@ static void activity_activate(struct led_classdev *led_cdev) led_activity_function(&activity_data->timer); set_bit(LED_BLINK_SW, &led_cdev->work_flags); led_cdev->activated = true; + + return 0; } static void activity_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/leds/trigger/ledtrig-backlight.c b/drivers/leds/trigger/ledtrig-backlight.c index 1ca1f1608f76..84512960d630 100644 --- a/drivers/leds/trigger/ledtrig-backlight.c +++ b/drivers/leds/trigger/ledtrig-backlight.c @@ -97,7 +97,7 @@ static ssize_t bl_trig_invert_store(struct device *dev, } static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store); -static void bl_trig_activate(struct led_classdev *led) +static int bl_trig_activate(struct led_classdev *led) { int ret; @@ -107,7 +107,7 @@ static void bl_trig_activate(struct led_classdev *led) led->trigger_data = n; if (!n) { dev_err(led->dev, "unable to allocate backlight trigger\n"); - return; + return 0; } ret = device_create_file(led->dev, &dev_attr_inverted); @@ -124,11 +124,13 @@ static void bl_trig_activate(struct led_classdev *led) dev_err(led->dev, "unable to register backlight trigger\n"); led->activated = true; - return; + return 0; err_invert: led->trigger_data = NULL; kfree(n); + + return 0; } static void bl_trig_deactivate(struct led_classdev *led) diff --git a/drivers/leds/trigger/ledtrig-default-on.c b/drivers/leds/trigger/ledtrig-default-on.c index 4ccea04b7a6b..2996fe672198 100644 --- a/drivers/leds/trigger/ledtrig-default-on.c +++ b/drivers/leds/trigger/ledtrig-default-on.c @@ -16,9 +16,10 @@ #include #include "../leds.h" -static void defon_trig_activate(struct led_classdev *led_cdev) +static int defon_trig_activate(struct led_classdev *led_cdev) { led_set_brightness_nosleep(led_cdev, led_cdev->max_brightness); + return 0; } static struct led_trigger defon_led_trigger = { diff --git a/drivers/leds/trigger/ledtrig-gpio.c b/drivers/leds/trigger/ledtrig-gpio.c index 93906a17a4b6..f5358c40d03f 100644 --- a/drivers/leds/trigger/ledtrig-gpio.c +++ b/drivers/leds/trigger/ledtrig-gpio.c @@ -162,14 +162,14 @@ static ssize_t gpio_trig_gpio_store(struct device *dev, } static DEVICE_ATTR(gpio, 0644, gpio_trig_gpio_show, gpio_trig_gpio_store); -static void gpio_trig_activate(struct led_classdev *led) +static int gpio_trig_activate(struct led_classdev *led) { struct gpio_trig_data *gpio_data; int ret; gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL); if (!gpio_data) - return; + return 0; ret = device_create_file(led->dev, &dev_attr_gpio); if (ret) @@ -187,7 +187,7 @@ static void gpio_trig_activate(struct led_classdev *led) led->trigger_data = gpio_data; led->activated = true; - return; + return 0; err_brightness: device_remove_file(led->dev, &dev_attr_inverted); @@ -197,6 +197,8 @@ err_inverted: err_gpio: kfree(gpio_data); + + return 0; } static void gpio_trig_deactivate(struct led_classdev *led) diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c index 304b929edb8e..03a8dfce8fb9 100644 --- a/drivers/leds/trigger/ledtrig-heartbeat.c +++ b/drivers/leds/trigger/ledtrig-heartbeat.c @@ -121,21 +121,21 @@ static ssize_t led_invert_store(struct device *dev, static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); -static void heartbeat_trig_activate(struct led_classdev *led_cdev) +static int heartbeat_trig_activate(struct led_classdev *led_cdev) { struct heartbeat_trig_data *heartbeat_data; int rc; heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); if (!heartbeat_data) - return; + return 0; led_cdev->trigger_data = heartbeat_data; heartbeat_data->led_cdev = led_cdev; rc = device_create_file(led_cdev->dev, &dev_attr_invert); if (rc) { kfree(led_cdev->trigger_data); - return; + return 0; } timer_setup(&heartbeat_data->timer, led_heartbeat_function, 0); @@ -145,6 +145,8 @@ static void heartbeat_trig_activate(struct led_classdev *led_cdev) led_heartbeat_function(&heartbeat_data->timer); set_bit(LED_BLINK_SW, &led_cdev->work_flags); led_cdev->activated = true; + + return 0; } static void heartbeat_trig_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index 6df4781a6308..bb05937255de 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -388,14 +388,14 @@ static void netdev_trig_work(struct work_struct *work) (atomic_read(&trigger_data->interval)*2)); } -static void netdev_trig_activate(struct led_classdev *led_cdev) +static int netdev_trig_activate(struct led_classdev *led_cdev) { struct led_netdev_data *trigger_data; int rc; trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); if (!trigger_data) - return; + return 0; spin_lock_init(&trigger_data->lock); @@ -432,7 +432,7 @@ static void netdev_trig_activate(struct led_classdev *led_cdev) rc = register_netdevice_notifier(&trigger_data->notifier); if (rc) goto err_out_interval; - return; + return 0; err_out_interval: device_remove_file(led_cdev->dev, &dev_attr_interval); @@ -447,6 +447,8 @@ err_out_device_name: err_out: led_cdev->trigger_data = NULL; kfree(trigger_data); + + return 0; } static void netdev_trig_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/leds/trigger/ledtrig-oneshot.c b/drivers/leds/trigger/ledtrig-oneshot.c index b8ea9f0f1e19..7bbf92bd7f80 100644 --- a/drivers/leds/trigger/ledtrig-oneshot.c +++ b/drivers/leds/trigger/ledtrig-oneshot.c @@ -122,14 +122,14 @@ static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); static DEVICE_ATTR(shot, 0200, NULL, led_shot); -static void oneshot_trig_activate(struct led_classdev *led_cdev) +static int oneshot_trig_activate(struct led_classdev *led_cdev) { struct oneshot_trig_data *oneshot_data; int rc; oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL); if (!oneshot_data) - return; + return 0; led_cdev->trigger_data = oneshot_data; @@ -151,7 +151,7 @@ static void oneshot_trig_activate(struct led_classdev *led_cdev) led_cdev->activated = true; - return; + return 0; err_out_invert: device_remove_file(led_cdev->dev, &dev_attr_invert); @@ -161,6 +161,8 @@ err_out_delayon: device_remove_file(led_cdev->dev, &dev_attr_delay_on); err_out_trig_data: kfree(led_cdev->trigger_data); + + return 0; } static void oneshot_trig_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/leds/trigger/ledtrig-timer.c b/drivers/leds/trigger/ledtrig-timer.c index 10fc0966b0e3..527055d815ad 100644 --- a/drivers/leds/trigger/ledtrig-timer.c +++ b/drivers/leds/trigger/ledtrig-timer.c @@ -70,7 +70,7 @@ static ssize_t led_delay_off_store(struct device *dev, static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store); static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); -static void timer_trig_activate(struct led_classdev *led_cdev) +static int timer_trig_activate(struct led_classdev *led_cdev) { int rc; @@ -78,7 +78,7 @@ static void timer_trig_activate(struct led_classdev *led_cdev) rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); if (rc) - return; + return 0; rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); if (rc) goto err_out_delayon; @@ -87,10 +87,12 @@ static void timer_trig_activate(struct led_classdev *led_cdev) &led_cdev->blink_delay_off); led_cdev->activated = true; - return; + return 0; err_out_delayon: device_remove_file(led_cdev->dev, &dev_attr_delay_on); + + return 0; } static void timer_trig_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/leds/trigger/ledtrig-transient.c b/drivers/leds/trigger/ledtrig-transient.c index 9d1769073562..a55fc58179a9 100644 --- a/drivers/leds/trigger/ledtrig-transient.c +++ b/drivers/leds/trigger/ledtrig-transient.c @@ -152,7 +152,7 @@ static DEVICE_ATTR(duration, 0644, transient_duration_show, transient_duration_store); static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store); -static void transient_trig_activate(struct led_classdev *led_cdev) +static int transient_trig_activate(struct led_classdev *led_cdev) { int rc; struct transient_trig_data *tdata; @@ -161,7 +161,7 @@ static void transient_trig_activate(struct led_classdev *led_cdev) if (!tdata) { dev_err(led_cdev->dev, "unable to allocate transient trigger\n"); - return; + return 0; } led_cdev->trigger_data = tdata; tdata->led_cdev = led_cdev; @@ -181,7 +181,7 @@ static void transient_trig_activate(struct led_classdev *led_cdev) timer_setup(&tdata->timer, transient_timer_function, 0); led_cdev->activated = true; - return; + return 0; err_out_state: device_remove_file(led_cdev->dev, &dev_attr_duration); @@ -191,6 +191,8 @@ err_out: dev_err(led_cdev->dev, "unable to register transient trigger\n"); led_cdev->trigger_data = NULL; kfree(tdata); + + return 0; } static void transient_trig_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index d5b4a2b44ab8..de310621b8e7 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -959,7 +959,7 @@ struct kbd_led_trigger { unsigned int mask; }; -static void kbd_led_trigger_activate(struct led_classdev *cdev) +static int kbd_led_trigger_activate(struct led_classdev *cdev) { struct kbd_led_trigger *trigger = container_of(cdev->trigger, struct kbd_led_trigger, trigger); @@ -970,6 +970,8 @@ static void kbd_led_trigger_activate(struct led_classdev *cdev) ledstate & trigger->mask ? LED_FULL : LED_OFF); tasklet_enable(&keyboard_tasklet); + + return 0; } #define KBD_LED_TRIGGER(_led_bit, _name) { \ diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c index d775ffea20c3..aa1d51458da7 100644 --- a/drivers/usb/core/ledtrig-usbport.c +++ b/drivers/usb/core/ledtrig-usbport.c @@ -298,14 +298,14 @@ static int usbport_trig_notify(struct notifier_block *nb, unsigned long action, return NOTIFY_DONE; } -static void usbport_trig_activate(struct led_classdev *led_cdev) +static int usbport_trig_activate(struct led_classdev *led_cdev) { struct usbport_trig_data *usbport_data; int err; usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL); if (!usbport_data) - return; + return 0; usbport_data->led_cdev = led_cdev; /* List of ports */ @@ -322,10 +322,11 @@ static void usbport_trig_activate(struct led_classdev *led_cdev) usb_register_notify(&usbport_data->nb); led_cdev->activated = true; - return; + return 0; err_free: kfree(usbport_data); + return 0; } static void usbport_trig_deactivate(struct led_classdev *led_cdev) diff --git a/include/linux/leds.h b/include/linux/leds.h index b7e82550e655..ba5baaaa43bf 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -253,7 +253,7 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) struct led_trigger { /* Trigger Properties */ const char *name; - void (*activate)(struct led_classdev *led_cdev); + int (*activate)(struct led_classdev *led_cdev); void (*deactivate)(struct led_classdev *led_cdev); /* LEDs under control by this trigger (for simple triggers) */ @@ -288,8 +288,8 @@ extern void led_trigger_blink_oneshot(struct led_trigger *trigger, unsigned long *delay_off, int invert); extern void led_trigger_set_default(struct led_classdev *led_cdev); -extern void led_trigger_set(struct led_classdev *led_cdev, - struct led_trigger *trigger); +extern int led_trigger_set(struct led_classdev *led_cdev, + struct led_trigger *trigger); extern void led_trigger_remove(struct led_classdev *led_cdev); static inline void *led_get_trigger_data(struct led_classdev *led_cdev) @@ -334,8 +334,12 @@ static inline void led_trigger_blink_oneshot(struct led_trigger *trigger, unsigned long *delay_off, int invert) {} static inline void led_trigger_set_default(struct led_classdev *led_cdev) {} -static inline void led_trigger_set(struct led_classdev *led_cdev, - struct led_trigger *trigger) {} +static inline int led_trigger_set(struct led_classdev *led_cdev, + struct led_t