diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-14 13:07:22 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-14 13:07:22 -0700 |
commit | c07b3682cd12a017f976ec63bbd4758dc4c5100e (patch) | |
tree | d158994137113f31a30feadaae80d3c5d7109a26 /drivers | |
parent | 4d88e3d24905eafa98cef0fc29365649ad8977b5 (diff) | |
parent | 2224f2ff9670b899983ff1b42d85530e889cfea1 (diff) |
Merge tag 'leds-for-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds
Pull LED updates from Jacek Anaszewski:
"LED triggers improvements make the biggest part of this pull request.
The most striking ones, that allowed for nice cleanups in the triggers
are:
- centralized handling of creation and removal of trigger sysfs
attributes via attribute group
- addition of module_led_trigger() helper
The other things that need to be mentioned:
New features and improvements to existing LED class drivers:
- lt3593: add DT support, switch to gpiod interface
- lm3692x: support LED sync configuration, change OF calls to fwnode
calls
- apu: modify PC Engines apu/apu2 driver to support apu3
Change in the drivers/net/can/led.c:
- mark led trigger as broken since it's in the way for the further
cleanups. It implements a subset of the netdev trigger and an Ack
is needed from someone who can actually test and confirm that the
netdev trigger works for can devices"
* tag 'leds-for-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds: (32 commits)
leds: ns2: Change unsigned to unsigned int
usb: simplify usbport trigger
leds: gpio trigger: simplifications from core changes
leds: backlight trigger: simplifications from core changes
leds: activity trigger: simplifications from core changes
leds: default-on trigger: make use of module_led_trigger()
leds: heartbeat trigger: simplifications from core changes
leds: oneshot trigger: simplifications from core changes
leds: transient trigger: simplifications from core changes
leds: timer trigger: simplifications from core changes
leds: netdev trigger: simplifications from core changes
leds: triggers: new function led_set_trigger_data()
leds: triggers: define module_led_trigger helper
leds: triggers: handle .trigger_data and .activated() in the core
leds: triggers: add device attribute support
leds: triggers: let struct led_trigger::activate() return an error code
leds: triggers: make the MODULE_LICENSE string match the actual license
leds: lm3692x: Support LED sync configuration
dt: bindings: lm3692x: Update binding for LED sync control
leds: lm3692x: Change DT calls to fwnode calls
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/leds/Kconfig | 5 | ||||
-rw-r--r-- | drivers/leds/led-triggers.c | 39 | ||||
-rw-r--r-- | drivers/leds/leds-apu.c | 44 | ||||
-rw-r--r-- | drivers/leds/leds-lm3692x.c | 181 | ||||
-rw-r--r-- | drivers/leds/leds-lt3593.c | 190 | ||||
-rw-r--r-- | drivers/leds/leds-max8997.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-ns2.c | 4 | ||||
-rw-r--r-- | drivers/leds/trigger/Kconfig | 15 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-activity.c | 51 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-backlight.c | 64 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-camera.c | 3 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-default-on.c | 20 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-gpio.c | 92 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-heartbeat.c | 49 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-netdev.c | 101 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-oneshot.c | 91 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-timer.c | 58 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-transient.c | 102 | ||||
-rw-r--r-- | drivers/net/can/Kconfig | 6 | ||||
-rw-r--r-- | drivers/tty/vt/keyboard.c | 4 | ||||
-rw-r--r-- | drivers/usb/core/ledtrig-usbport.c | 34 |
21 files changed, 551 insertions, 604 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/led-triggers.c b/drivers/leds/led-triggers.c index 431123b048a2..17d73db1456e 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); @@ -126,7 +127,10 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) led_stop_software_blink(led_cdev); if (led_cdev->trigger->deactivate) led_cdev->trigger->deactivate(led_cdev); + device_remove_groups(led_cdev->dev, led_cdev->trigger->groups); led_cdev->trigger = NULL; + led_cdev->trigger_data = NULL; + led_cdev->activated = false; led_set_brightness(led_cdev, LED_OFF); } if (trig) { @@ -134,8 +138,20 @@ 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; + + ret = device_add_groups(led_cdev->dev, trig->groups); + if (ret) { + dev_err(led_cdev->dev, "Failed to add trigger attributes\n"); + goto err_add_groups; + } } if (event) { @@ -146,6 +162,23 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) "%s: Error sending uevent\n", __func__); kfree(event); } + + return 0; + +err_add_groups: + + if (trig->deactivate) + trig->deactivate(led_cdev); +err_activate: + + led_cdev->trigger = NULL; + led_cdev->trigger_data = 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/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; diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index 437173d1712c..4f413a7c5f05 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 <dmurphy@ti.com> - * - * 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 <linux/gpio/consumer.h> #include <linux/i2c.h> @@ -26,6 +15,9 @@ #include <linux/slab.h> #include <uapi/linux/uleds.h> +#define LM36922_MODEL 0 +#define LM36923_MODEL 1 + #define LM3692X_REV 0x0 #define LM3692X_RESET 0x1 #define LM3692X_EN 0x10 @@ -44,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) @@ -109,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; @@ -118,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[] = { @@ -200,6 +199,7 @@ out: static int lm3692x_init(struct lm3692x_led *led) { + int enable_state; int ret; if (led->regulator) { @@ -226,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) @@ -258,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"); @@ -274,52 +322,75 @@ 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) { - int ret; - struct lm3692x_led *led; - struct device_node *np = client->dev.of_node; - struct device_node *child_node; + struct fwnode_handle *child = NULL; 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, + 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; + child = device_get_next_child_node(&led->client->dev, child); + if (!child) { + dev_err(&led->client->dev, "No LED Child node\n"); + return -ENODEV; + } + + 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); + + 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; - led->led_dev.brightness_set_blocking = lm3692x_brightness_set; - mutex_init(&led->lock); + ret = devm_led_classdev_register(&led->client->dev, &led->led_dev); + if (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); @@ -330,15 +401,13 @@ static int lm3692x_probe(struct i2c_client *client, return ret; } - ret = lm3692x_init(led); + ret = lm3692x_probe_dt(led); if (ret) return ret; - ret = devm_led_classdev_register(&client->dev, &led->led_dev); - if (ret) { - dev_err(&client->dev, "led register err: %d\n", ret); + ret = lm3692x_init(led); + if (ret) return ret; - } return 0; } @@ -348,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); @@ -364,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); diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 5ec730a31b65..de3623e0d094 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -1,32 +1,21 @@ -/* - * LEDs driver for LT3593 controllers - * - * See the datasheet at http://cds.linear.com/docs/Datasheet/3593f.pdf - * - * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> - * - * Based on leds-gpio.c, - * - * Copyright (C) 2007 8D Technologies inc. - * Raphael Assenat <raph@8d.com> - * 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 <daniel@zonque.org> #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/leds.h> #include <linux/delay.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/of.h> +#include <uapi/linux/uleds.h> struct lt3593_led_data { + char name[LED_MAX_NAME_SIZE]; struct led_classdev cdev; - unsigned gpio; + struct gpio_desc *gpiod; }; static int lt3593_led_set(struct led_classdev *led_cdev, @@ -46,137 +35,168 @@ 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); } 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 (!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; - } + if (pdata->num_leds != 1) + return ERR_PTR(-EINVAL); - led_dat->cdev.name = template->name; - led_dat->cdev.default_trigger = template->default_trigger; - led_dat->gpio = template->gpio; + led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL); + if (!led_data) + return ERR_PTR(-ENOMEM); - 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->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; - - ret = led_classdev_register(parent, &led_dat->cdev); - if (ret < 0) - return ret; + return ERR_PTR(ret); - dev_info(parent, "%s: registered LT3593 LED '%s' at GPIO %d\n", - KBUILD_MODNAME, template->name, template->gpio); + led_data->gpiod = gpio_to_desc(template->gpio); + if (!led_data->gpiod) + return ERR_PTR(-EPROBE_DEFER); - return 0; -} + ret = devm_led_classdev_register(dev, &led_data->cdev); + if (ret < 0) + return ERR_PTR(ret); -static void delete_lt3593_led(struct lt3593_led_data *led) -{ - if (!gpio_is_valid(led->gpio)) - return; + dev_info(dev, "registered LT3593 LED '%s' at GPIO %d\n", + template->name, template->gpio); - 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; + 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 (!pdata) - return -EBUSY; + if (!dev->of_node) + return -ENODEV; - leds_data = devm_kcalloc(&pdev->dev, - pdata->num_leds, sizeof(struct lt3593_led_data), - GFP_KERNEL); - if (!leds_data) + led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL); + if (!led_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; + if (device_get_child_node_count(dev) != 1) { + dev_err(dev, "Device must have exactly one LED sub-node."); + return -EINVAL; } - platform_set_drvdata(pdev, leds_data); + led_data->gpiod = devm_gpiod_get(dev, "lltc,ctrl", 0); + if (IS_ERR(led_data->gpiod)) + return PTR_ERR(led_data->gpiod); - return 0; + child = device_get_next_child_node(dev, NULL); -err: - for (i = i - 1; i >= 0; i--) - delete_lt3593_led(&leds_data[i]); + 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; + } + } - return ret; -} + 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; -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; + ret = devm_led_classdev_register(dev, &led_data->cdev); + if (ret < 0) { + fwnode_handle_put(child); + return ret; + } - leds_data = platform_get_drvdata(pdev); + led_data->cdev.dev->of_node = dev->of_node; - for (i = 0; i < pdata->num_leds; i++) - delete_lt3593_led(&leds_data[i]); +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, - .remove = lt3593_led_remove, .driver = { .name = "leds-lt3593", + .of_match_table = of_match_ptr(of_lt3593_leds_match), }, }; module_platform_driver(lt3593_led_driver); -MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); +MODULE_AUTHOR("Daniel Mack <daniel@zonque.org>"); MODULE_DESCRIPTION("LED driver for LT3593 controllers"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:leds-lt3593"); 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; diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 14fe5cd43232..a0a7dc2ef87c 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -42,8 +42,8 @@ struct ns2_led_data { struct led_classdev cdev; - unsigned cmd; - unsigned slow; + unsigned int cmd; + unsigned int slow; bool can_sleep; unsigned char sata; /* True when SATA mode active. */ rwlock_t rw_lock; /* Lock GPIOs. */ 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 c |