Commit 5f9cc570 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'leds_for_4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds

Pull LED updates from Jacek Anaszewski:
 "LED class drivers improvements:

  leds-pca955x:
   - add Device Tree support and bindings
   - use devm_led_classdev_register()
   - add GPIO support
   - prevent crippled LED class device name
   - check for I2C errors

  leds-gpio:
   - add optional retain-state-shutdown DT property
   - allow LED to retain state at shutdown

  leds-tlc591xx:
   - merge conditional tests
   - add missing of_node_put

  leds-powernv:
   - delete an error message for a failed memory allocation in
     powernv_led_create()

  leds-is31fl32xx.c
   - convert to using custom %pOF printf format specifier

  Constify attribute_group structures in:
   - leds-blinkm
   - leds-lm3533

  Make several arrays static const in:
   - leds-aat1290
   - leds-lp5521
   - leds-lp5562
   - leds-lp8501"

* tag 'leds_for_4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds:
  leds: pca955x: check for I2C errors
  leds: gpio: Allow LED to retain state at shutdown
  dt-bindings: leds: gpio: Add optional retain-state-shutdown property
  leds: powernv: Delete an error message for a failed memory allocation in powernv_led_create()
  leds: lp8501: make several arrays static const
  leds: lp5562: make several arrays static const
  leds: lp5521: make several arrays static const
  leds: aat1290: make array max_mm_current_percent static const
  leds: pca955x: Prevent crippled LED device name
  leds: lm3533: constify attribute_group structure
  dt-bindings: leds: add pca955x
  leds: pca955x: add GPIO support
  leds: pca955x: use devm_led_classdev_register
  leds: pca955x: add device tree support
  leds: Convert to using %pOF instead of full_name
  leds: blinkm: constify attribute_group structures.
  leds: tlc591xx: add missing of_node_put
  leds: tlc591xx: merge conditional tests
parents cd7b34fe 1591caf2
...@@ -18,6 +18,9 @@ LED sub-node properties: ...@@ -18,6 +18,9 @@ LED sub-node properties:
see Documentation/devicetree/bindings/leds/common.txt see Documentation/devicetree/bindings/leds/common.txt
- retain-state-suspended: (optional) The suspend state can be retained.Such - retain-state-suspended: (optional) The suspend state can be retained.Such
as charge-led gpio. as charge-led gpio.
- retain-state-shutdown: (optional) Retain the state of the LED on shutdown.
Useful in BMC systems, for example when the BMC is rebooted while the host
remains up.
- panic-indicator : (optional) - panic-indicator : (optional)
see Documentation/devicetree/bindings/leds/common.txt see Documentation/devicetree/bindings/leds/common.txt
......
* NXP - pca955x LED driver
The PCA955x family of chips are I2C LED blinkers whose pins not used
to control LEDs can be used as general purpose I/Os. The GPIO pins can
be input or output, and output pins can also be pulse-width controlled.
Required properties:
- compatible : should be one of :
"nxp,pca9550"
"nxp,pca9551"
"nxp,pca9552"
"nxp,pca9553"
- #address-cells: must be 1
- #size-cells: must be 0
- reg: I2C slave address. depends on the model.
Optional properties:
- gpio-controller: allows pins to be used as GPIOs.
- #gpio-cells: must be 2.
- gpio-line-names: define the names of the GPIO lines
LED sub-node properties:
- reg : number of LED line.
from 0 to 1 for the pca9550
from 0 to 7 for the pca9551
from 0 to 15 for the pca9552
from 0 to 3 for the pca9553
- type: (optional) either
PCA9532_TYPE_NONE
PCA9532_TYPE_LED
PCA9532_TYPE_GPIO
see dt-bindings/leds/leds-pca955x.h (default to LED)
- label : (optional)
see Documentation/devicetree/bindings/leds/common.txt
- linux,default-trigger : (optional)
see Documentation/devicetree/bindings/leds/common.txt
Examples:
pca9552: pca9552@60 {
compatible = "nxp,pca9552";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x60>;
gpio-controller;
#gpio-cells = <2>;
gpio-line-names = "GPIO12", "GPIO13", "GPIO14", "GPIO15";
gpio@12 {
reg = <12>;
type = <PCA955X_TYPE_GPIO>;
};
gpio@13 {
reg = <13>;
type = <PCA955X_TYPE_GPIO>;
};
gpio@14 {
reg = <14>;
type = <PCA955X_TYPE_GPIO>;
};
gpio@15 {
reg = <15>;
type = <PCA955X_TYPE_GPIO>;
};
led@0 {
label = "red:power";
linux,default-trigger = "default-on";
reg = <0>;
type = <PCA955X_TYPE_LED>;
};
led@1 {
label = "green:power";
reg = <1>;
type = <PCA955X_TYPE_LED>;
};
led@2 {
label = "pca9552:yellow";
reg = <2>;
type = <PCA955X_TYPE_LED>;
};
led@3 {
label = "pca9552:white";
reg = <3>;
type = <PCA955X_TYPE_LED>;
};
};
...@@ -386,6 +386,17 @@ config LEDS_PCA955X ...@@ -386,6 +386,17 @@ config LEDS_PCA955X
LED driver chips accessed via the I2C bus. Supported LED driver chips accessed via the I2C bus. Supported
devices include PCA9550, PCA9551, PCA9552, and PCA9553. devices include PCA9550, PCA9551, PCA9552, and PCA9553.
config LEDS_PCA955X_GPIO
bool "Enable GPIO support for PCA955X"
depends on LEDS_PCA955X
depends on GPIOLIB
help
Allow unused pins on PCA955X to be used as gpio.
To use a pin as gpio the pin type should be set to
PCA955X_TYPE_GPIO in the device tree.
config LEDS_PCA963X config LEDS_PCA963X
tristate "LED support for PCA963x I2C chip" tristate "LED support for PCA963x I2C chip"
depends on LEDS_CLASS depends on LEDS_CLASS
......
...@@ -314,8 +314,10 @@ static void aat1290_led_validate_mm_current(struct aat1290_led *led, ...@@ -314,8 +314,10 @@ static void aat1290_led_validate_mm_current(struct aat1290_led *led,
static int init_mm_current_scale(struct aat1290_led *led, static int init_mm_current_scale(struct aat1290_led *led,
struct aat1290_led_config_data *cfg) struct aat1290_led_config_data *cfg)
{ {
int max_mm_current_percent[] = { 20, 22, 25, 28, 32, 36, 40, 45, 50, 56, static const int max_mm_current_percent[] = {
63, 71, 79, 89, 100 }; 20, 22, 25, 28, 32, 36, 40, 45, 50, 56,
63, 71, 79, 89, 100
};
int i, max_mm_current = int i, max_mm_current =
AAT1290_MAX_MM_CURRENT(cfg->max_flash_current); AAT1290_MAX_MM_CURRENT(cfg->max_flash_current);
......
...@@ -298,7 +298,7 @@ static struct attribute *blinkm_attrs[] = { ...@@ -298,7 +298,7 @@ static struct attribute *blinkm_attrs[] = {
NULL, NULL,
}; };
static struct attribute_group blinkm_group = { static const struct attribute_group blinkm_group = {
.name = "blinkm", .name = "blinkm",
.attrs = blinkm_attrs, .attrs = blinkm_attrs,
}; };
......
...@@ -134,6 +134,8 @@ static int create_gpio_led(const struct gpio_led *template, ...@@ -134,6 +134,8 @@ static int create_gpio_led(const struct gpio_led *template,
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
if (template->panic_indicator) if (template->panic_indicator)
led_dat->cdev.flags |= LED_PANIC_INDICATOR; led_dat->cdev.flags |= LED_PANIC_INDICATOR;
if (template->retain_state_shutdown)
led_dat->cdev.flags |= LED_RETAIN_AT_SHUTDOWN;
ret = gpiod_direction_output(led_dat->gpiod, state); ret = gpiod_direction_output(led_dat->gpiod, state);
if (ret < 0) if (ret < 0)
...@@ -205,6 +207,8 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) ...@@ -205,6 +207,8 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
if (fwnode_property_present(child, "retain-state-suspended")) if (fwnode_property_present(child, "retain-state-suspended"))
led.retain_state_suspended = 1; led.retain_state_suspended = 1;
if (fwnode_property_present(child, "retain-state-shutdown"))
led.retain_state_shutdown = 1;
if (fwnode_property_present(child, "panic-indicator")) if (fwnode_property_present(child, "panic-indicator"))
led.panic_indicator = 1; led.panic_indicator = 1;
...@@ -267,7 +271,8 @@ static void gpio_led_shutdown(struct platform_device *pdev) ...@@ -267,7 +271,8 @@ static void gpio_led_shutdown(struct platform_device *pdev)
for (i = 0; i < priv->num_leds; i++) { for (i = 0; i < priv->num_leds; i++) {
struct gpio_led_data *led = &priv->leds[i]; struct gpio_led_data *led = &priv->leds[i];
gpio_led_set(&led->cdev, LED_OFF); if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN))
gpio_led_set(&led->cdev, LED_OFF);
} }
} }
......
...@@ -348,8 +348,8 @@ static int is31fl32xx_parse_child_dt(const struct device *dev, ...@@ -348,8 +348,8 @@ static int is31fl32xx_parse_child_dt(const struct device *dev,
ret = of_property_read_u32(child, "reg", &reg); ret = of_property_read_u32(child, "reg", &reg);
if (ret || reg < 1 || reg > led_data->priv->cdef->channels) { if (ret || reg < 1 || reg > led_data->priv->cdef->channels) {
dev_err(dev, dev_err(dev,
"Child node %s does not have a valid reg property\n", "Child node %pOF does not have a valid reg property\n",
child->full_name); child);
return -EINVAL; return -EINVAL;
} }
led_data->channel = reg; led_data->channel = reg;
......
...@@ -626,7 +626,7 @@ static umode_t lm3533_led_attr_is_visible(struct kobject *kobj, ...@@ -626,7 +626,7 @@ static umode_t lm3533_led_attr_is_visible(struct kobject *kobj,
return mode; return mode;
}; };
static struct attribute_group lm3533_led_attribute_group = { static const struct attribute_group lm3533_led_attribute_group = {
.is_visible = lm3533_led_attr_is_visible, .is_visible = lm3533_led_attr_is_visible,
.attrs = lm3533_led_attributes .attrs = lm3533_led_attributes
}; };
......
...@@ -134,13 +134,13 @@ static void lp5521_set_led_current(struct lp55xx_led *led, u8 led_current) ...@@ -134,13 +134,13 @@ static void lp5521_set_led_current(struct lp55xx_led *led, u8 led_current)
static void lp5521_load_engine(struct lp55xx_chip *chip) static void lp5521_load_engine(struct lp55xx_chip *chip)
{ {
enum lp55xx_engine_index idx = chip->engine_idx; enum lp55xx_engine_index idx = chip->engine_idx;
u8 mask[] = { static const u8 mask[] = {
[LP55XX_ENGINE_1] = LP5521_MODE_R_M, [LP55XX_ENGINE_1] = LP5521_MODE_R_M,
[LP55XX_ENGINE_2] = LP5521_MODE_G_M, [LP55XX_ENGINE_2] = LP5521_MODE_G_M,
[LP55XX_ENGINE_3] = LP5521_MODE_B_M, [LP55XX_ENGINE_3] = LP5521_MODE_B_M,
}; };
u8 val[] = { static const u8 val[] = {
[LP55XX_ENGINE_1] = LP5521_LOAD_R, [LP55XX_ENGINE_1] = LP5521_LOAD_R,
[LP55XX_ENGINE_2] = LP5521_LOAD_G, [LP55XX_ENGINE_2] = LP5521_LOAD_G,
[LP55XX_ENGINE_3] = LP5521_LOAD_B, [LP55XX_ENGINE_3] = LP5521_LOAD_B,
...@@ -160,7 +160,7 @@ static void lp5521_stop_all_engines(struct lp55xx_chip *chip) ...@@ -160,7 +160,7 @@ static void lp5521_stop_all_engines(struct lp55xx_chip *chip)
static void lp5521_stop_engine(struct lp55xx_chip *chip) static void lp5521_stop_engine(struct lp55xx_chip *chip)
{ {
enum lp55xx_engine_index idx = chip->engine_idx; enum lp55xx_engine_index idx = chip->engine_idx;
u8 mask[] = { static const u8 mask[] = {
[LP55XX_ENGINE_1] = LP5521_MODE_R_M, [LP55XX_ENGINE_1] = LP5521_MODE_R_M,
[LP55XX_ENGINE_2] = LP5521_MODE_G_M, [LP55XX_ENGINE_2] = LP5521_MODE_G_M,
[LP55XX_ENGINE_3] = LP5521_MODE_B_M, [LP55XX_ENGINE_3] = LP5521_MODE_B_M,
...@@ -226,7 +226,7 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip, ...@@ -226,7 +226,7 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip,
{ {
enum lp55xx_engine_index idx = chip->engine_idx; enum lp55xx_engine_index idx = chip->engine_idx;
u8 pattern[LP5521_PROGRAM_LENGTH] = {0}; u8 pattern[LP5521_PROGRAM_LENGTH] = {0};
u8 addr[] = { static const u8 addr[] = {
[LP55XX_ENGINE_1] = LP5521_REG_R_PROG_MEM, [LP55XX_ENGINE_1] = LP5521_REG_R_PROG_MEM,
[LP55XX_ENGINE_2] = LP5521_REG_G_PROG_MEM, [LP55XX_ENGINE_2] = LP5521_REG_G_PROG_MEM,
[LP55XX_ENGINE_3] = LP5521_REG_B_PROG_MEM, [LP55XX_ENGINE_3] = LP5521_REG_B_PROG_MEM,
......
...@@ -116,7 +116,7 @@ static inline void lp5562_wait_enable_done(void) ...@@ -116,7 +116,7 @@ static inline void lp5562_wait_enable_done(void)
static void lp5562_set_led_current(struct lp55xx_led *led, u8 led_current) static void lp5562_set_led_current(struct lp55xx_led *led, u8 led_current)
{ {
u8 addr[] = { static const u8 addr[] = {
LP5562_REG_R_CURRENT, LP5562_REG_R_CURRENT,
LP5562_REG_G_CURRENT, LP5562_REG_G_CURRENT,
LP5562_REG_B_CURRENT, LP5562_REG_B_CURRENT,
...@@ -130,13 +130,13 @@ static void lp5562_set_led_current(struct lp55xx_led *led, u8 led_current) ...@@ -130,13 +130,13 @@ static void lp5562_set_led_current(struct lp55xx_led *led, u8 led_current)
static void lp5562_load_engine(struct lp55xx_chip *chip) static void lp5562_load_engine(struct lp55xx_chip *chip)
{ {
enum lp55xx_engine_index idx = chip->engine_idx; enum lp55xx_engine_index idx = chip->engine_idx;
u8 mask[] = { static const u8 mask[] = {
[LP55XX_ENGINE_1] = LP5562_MODE_ENG1_M, [LP55XX_ENGINE_1] = LP5562_MODE_ENG1_M,
[LP55XX_ENGINE_2] = LP5562_MODE_ENG2_M, [LP55XX_ENGINE_2] = LP5562_MODE_ENG2_M,
[LP55XX_ENGINE_3] = LP5562_MODE_ENG3_M, [LP55XX_ENGINE_3] = LP5562_MODE_ENG3_M,
}; };
u8 val[] = { static const u8 val[] = {
[LP55XX_ENGINE_1] = LP5562_LOAD_ENG1, [LP55XX_ENGINE_1] = LP5562_LOAD_ENG1,
[LP55XX_ENGINE_2] = LP5562_LOAD_ENG2, [LP55XX_ENGINE_2] = LP5562_LOAD_ENG2,
[LP55XX_ENGINE_3] = LP5562_LOAD_ENG3, [LP55XX_ENGINE_3] = LP5562_LOAD_ENG3,
...@@ -211,7 +211,7 @@ static int lp5562_update_firmware(struct lp55xx_chip *chip, ...@@ -211,7 +211,7 @@ static int lp5562_update_firmware(struct lp55xx_chip *chip,
{ {
enum lp55xx_engine_index idx = chip->engine_idx; enum lp55xx_engine_index idx = chip->engine_idx;
u8 pattern[LP5562_PROGRAM_LENGTH] = {0}; u8 pattern[LP5562_PROGRAM_LENGTH] = {0};
u8 addr[] = { static const u8 addr[] = {
[LP55XX_ENGINE_1] = LP5562_REG_PROG_MEM_ENG1, [LP55XX_ENGINE_1] = LP5562_REG_PROG_MEM_ENG1,
[LP55XX_ENGINE_2] = LP5562_REG_PROG_MEM_ENG2, [LP55XX_ENGINE_2] = LP5562_REG_PROG_MEM_ENG2,
[LP55XX_ENGINE_3] = LP5562_REG_PROG_MEM_ENG3, [LP55XX_ENGINE_3] = LP5562_REG_PROG_MEM_ENG3,
...@@ -314,7 +314,7 @@ static int lp5562_post_init_device(struct lp55xx_chip *chip) ...@@ -314,7 +314,7 @@ static int lp5562_post_init_device(struct lp55xx_chip *chip)
static int lp5562_led_brightness(struct lp55xx_led *led) static int lp5562_led_brightness(struct lp55xx_led *led)
{ {
struct lp55xx_chip *chip = led->chip; struct lp55xx_chip *chip = led->chip;
u8 addr[] = { static const u8 addr[] = {
LP5562_REG_R_PWM, LP5562_REG_R_PWM,
LP5562_REG_G_PWM, LP5562_REG_G_PWM,
LP5562_REG_B_PWM, LP5562_REG_B_PWM,
......
...@@ -118,19 +118,19 @@ static int lp8501_post_init_device(struct lp55xx_chip *chip) ...@@ -118,19 +118,19 @@ static int lp8501_post_init_device(struct lp55xx_chip *chip)
static void lp8501_load_engine(struct lp55xx_chip *chip) static void lp8501_load_engine(struct lp55xx_chip *chip)
{ {
enum lp55xx_engine_index idx = chip->engine_idx; enum lp55xx_engine_index idx = chip->engine_idx;
u8 mask[] = { static const u8 mask[] = {
[LP55XX_ENGINE_1] = LP8501_MODE_ENG1_M, [LP55XX_ENGINE_1] = LP8501_MODE_ENG1_M,
[LP55XX_ENGINE_2] = LP8501_MODE_ENG2_M, [LP55XX_ENGINE_2] = LP8501_MODE_ENG2_M,
[LP55XX_ENGINE_3] = LP8501_MODE_ENG3_M, [LP55XX_ENGINE_3] = LP8501_MODE_ENG3_M,
}; };
u8 val[] = { static const u8 val[] = {
[LP55XX_ENGINE_1] = LP8501_LOAD_ENG1, [LP55XX_ENGINE_1] = LP8501_LOAD_ENG1,
[LP55XX_ENGINE_2] = LP8501_LOAD_ENG2, [LP55XX_ENGINE_2] = LP8501_LOAD_ENG2,
[LP55XX_ENGINE_3] = LP8501_LOAD_ENG3, [LP55XX_ENGINE_3] = LP8501_LOAD_ENG3,
}; };
u8 page_sel[] = { static const u8 page_sel[] = {
[LP55XX_ENGINE_1] = LP8501_PAGE_ENG1, [LP55XX_ENGINE_1] = LP8501_PAGE_ENG1,
[LP55XX_ENGINE_2] = LP8501_PAGE_ENG2, [LP55XX_ENGINE_2] = LP8501_PAGE_ENG2,
[LP55XX_ENGINE_3] = LP8501_PAGE_ENG3, [LP55XX_ENGINE_3] = LP8501_PAGE_ENG3,
......
This diff is collapsed.
...@@ -224,12 +224,8 @@ static int powernv_led_create(struct device *dev, ...@@ -224,12 +224,8 @@ static int powernv_led_create(struct device *dev,
powernv_led->cdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", powernv_led->cdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s",
powernv_led->loc_code, powernv_led->loc_code,
led_type_desc); led_type_desc);
if (!powernv_led->cdev.name) { if (!powernv_led->cdev.name)
dev_err(dev,
"%s: Memory allocation failed for classdev name\n",
__func__);
return -ENOMEM; return -ENOMEM;
}
powernv_led->cdev.brightness_set_blocking = powernv_brightness_set; powernv_led->cdev.brightness_set_blocking = powernv_brightness_set;
powernv_led->cdev.brightness_get = powernv_brightness_get; powernv_led->cdev.brightness_get = powernv_brightness_get;
......
...@@ -230,12 +230,15 @@ tlc591xx_probe(struct i2c_client *client, ...@@ -230,12 +230,15 @@ tlc591xx_probe(struct i2c_client *client,
for_each_child_of_node(np, child) { for_each_child_of_node(np, child) {
err = of_property_read_u32(child, "reg", &reg); err = of_property_read_u32(child, "reg", &reg);
if (err) if (err) {
of_node_put(child);
return err; return err;
if (reg < 0 || reg >= tlc591xx->max_leds) }
return -EINVAL; if (reg < 0 || reg >= tlc591xx->max_leds ||
if (priv->leds[reg].active) priv->leds[reg].active) {
of_node_put(child);
return -EINVAL; return -EINVAL;
}
priv->leds[reg].active = true; priv->leds[reg].active = true;
priv->leds[reg].ldev.name = priv->leds[reg].ldev.name =
of_get_property(child, "label", NULL) ? : child->name; of_get_property(child, "label", NULL) ? : child->name;
......
/*
* This header provides constants for pca955x LED bindings.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef _DT_BINDINGS_LEDS_PCA955X_H
#define _DT_BINDINGS_LEDS_PCA955X_H
#define PCA955X_TYPE_NONE 0
#define PCA955X_TYPE_LED 1
#define PCA955X_TYPE_GPIO 2
#endif /* _DT_BINDINGS_LEDS_PCA955X_H */
...@@ -49,6 +49,7 @@ struct led_classdev { ...@@ -49,6 +49,7 @@ struct led_classdev {
#define LED_HW_PLUGGABLE (1 << 19) #define LED_HW_PLUGGABLE (1 << 19)
#define LED_PANIC_INDICATOR (1 << 20) #define LED_PANIC_INDICATOR (1 << 20)
#define LED_BRIGHT_HW_CHANGED (1 << 21) #define LED_BRIGHT_HW_CHANGED (1 << 21)
#define LED_RETAIN_AT_SHUTDOWN (1 << 22)
/* set_brightness_work / blink_timer flags, atomic, private. */ /* set_brightness_work / blink_timer flags, atomic, private. */
unsigned long work_flags; unsigned long work_flags;
...@@ -392,6 +393,7 @@ struct gpio_led { ...@@ -392,6 +393,7 @@ struct gpio_led {
unsigned retain_state_suspended : 1; unsigned retain_state_suspended : 1;
unsigned panic_indicator : 1; unsigned panic_indicator : 1;
unsigned default_state : 2; unsigned default_state : 2;
unsigned retain_state_shutdown : 1;
/* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */ /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
struct gpio_desc *gpiod; struct gpio_desc *gpiod;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment