This commit is contained in:
Mark Brown
2026-07-31 16:03:14 +01:00
19 changed files with 1027 additions and 221 deletions
@@ -0,0 +1,133 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/leds/adi,ltc3220.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices LTC3220 LED Driver
maintainers:
- Edelweise Escala <edelweise.escala@analog.com>
description: >
The LTC3220 is a multi-display LED driver, which contains a high-efficiency,
low-noise charge pump to provide power to up to 18 LED current sources.
The LEDs are individually configurable to 64-step linear brightness control,
blinking and gradation control via 2-wire I2C interface.
For more product information please see the link below
https://www.analog.com/en/products/ltc3220.html
properties:
compatible:
const: adi,ltc3220
reg:
maxItems: 1
'#address-cells':
const: 1
'#size-cells':
const: 0
reset-gpios:
maxItems: 1
patternProperties:
'^led@([1-9a-f]|1[0-2])$':
type: object
$ref: /schemas/leds/common.yaml#
unevaluatedProperties: false
properties:
reg:
description:
Output channel for the LED (1-18 maps to LED outputs D1-D18).
Unit-address must be in hexadecimal (1-12 hex = 1-18 decimal).
For aggregated LED control, define only one LED node with reg = <0x1>
and use led-sources to list all controlled outputs. Only reg 1 should
be present when using led-sources.
items:
- minimum: 1
maximum: 18
required:
- reg
if:
required:
- led-sources
then:
properties:
reg:
items:
- const: 1
required:
- compatible
- reg
- '#address-cells'
- '#size-cells'
additionalProperties: false
examples:
- |
// Independent LEDs
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
led-controller@1c {
compatible = "adi,ltc3220";
reg = <0x1c>;
#address-cells = <1>;
#size-cells = <0>;
reset-gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
led@1 {
reg = <0x1>;
function = LED_FUNCTION_INDICATOR;
function-enumerator = <1>;
};
led@2 {
reg = <0x2>;
function = LED_FUNCTION_INDICATOR;
function-enumerator = <2>;
};
led@3 {
reg = <0x3>;
function = LED_FUNCTION_INDICATOR;
function-enumerator = <3>;
};
};
};
- |
// Aggregated LED
#include <dt-bindings/leds/common.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
led-controller@1c {
compatible = "adi,ltc3220";
reg = <0x1c>;
#address-cells = <1>;
#size-cells = <0>;
led@1 {
reg = <0x1>;
led-sources = <0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 0x11 0x12>;
function = LED_FUNCTION_BACKLIGHT;
};
};
};
...
@@ -0,0 +1,96 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/leds/brcm,bcm6358-leds.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: LEDs connected to Broadcom BCM6358 controller
description: |
This controller is present on BCM6358 and BCM6368.
In these SoCs there are Serial LEDs (LEDs connected to a 74x164 controller),
which can either be controlled by software (exporting the 74x164 as spi-gpio.
See Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml), or
by hardware using this driver.
maintainers:
- Álvaro Fernández Rojas <noltari@gmail.com>
properties:
compatible:
const: brcm,bcm6358-leds
reg:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 0
brcm,clk-div:
description: SCK signal divider.
default: 1
$ref: /schemas/types.yaml#/definitions/uint32
enum: [1, 2, 4, 8]
brcm,clk-dat-low:
description: Makes clock and data signals active low.
type: boolean
patternProperties:
"^led@1?[0-9a-f]$":
type: object
$ref: common.yaml#
unevaluatedProperties: false
description: Each LED is represented as a sub-node of
this device.
properties:
reg:
description: LED pin number (0 to 31).
maxItems: 1
required:
- reg
required:
- compatible
- reg
- "#address-cells"
- "#size-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/leds/common.h>
led-controller@fffe00d0 {
compatible = "brcm,bcm6358-leds";
#address-cells = <1>;
#size-cells = <0>;
reg = <0xfffe00d0 0x8>;
led@0 {
reg = <0>;
active-low;
label = "white:alarm";
};
led@2 {
reg = <2>;
active-low;
label = "white:tv";
};
led@3 {
reg = <3>;
active-low;
label = "white:tel";
};
led@4 {
reg = <4>;
active-low;
label = "white:adsl";
};
};
...
@@ -73,6 +73,16 @@ properties:
- keep
default: off
default-intensity:
description:
The initial intensity of the LED color component. As the intensity of
each sub-LED is multiplied with the overall brightness, without this
property on a sub-LED, it may effectively be initialized at minimum
brightness regardless of its linux,default-trigger and default-brightness
properties.
$ref: /schemas/types.yaml#/definitions/uint32
default: 0
linux,default-trigger:
description:
This parameter, if present, is a string defining the trigger assigned to
@@ -106,6 +116,8 @@ properties:
- bluetooth-power
# LED indicates camera flash state
- flash
# LED indicates level of GPIO input referenced by trigger-sources
- gpio
# LED indicated keyboard capslock
- kbd-capslock
# LED indicates MTD memory activity
@@ -1,143 +0,0 @@
LEDs connected to Broadcom BCM6358 controller
This controller is present on BCM6358 and BCM6368.
In these SoCs there are Serial LEDs (LEDs connected to a 74x164 controller),
which can either be controlled by software (exporting the 74x164 as spi-gpio.
See Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml), or
by hardware using this driver.
Required properties:
- compatible : should be "brcm,bcm6358-leds".
- #address-cells : must be 1.
- #size-cells : must be 0.
- reg : BCM6358 LED controller address and size.
Optional properties:
- brcm,clk-div : SCK signal divider. Possible values are 1, 2, 4 and 8.
Default : 1
- brcm,clk-dat-low : Boolean, makes clock and data signals active low.
Default : false
Each LED is represented as a sub-node of the brcm,bcm6358-leds device.
LED sub-node required properties:
- reg : LED pin number (only LEDs 0 to 31 are valid).
LED sub-node optional properties:
- label : see Documentation/devicetree/bindings/leds/common.txt
- default-state : see
Documentation/devicetree/bindings/leds/common.txt
- linux,default-trigger : see
Documentation/devicetree/bindings/leds/common.txt
Examples:
Scenario 1 : BCM6358
leds0: led-controller@fffe00d0 {
compatible = "brcm,bcm6358-leds";
#address-cells = <1>;
#size-cells = <0>;
reg = <0xfffe00d0 0x8>;
alarm_white {
reg = <0>;
active-low;
label = "white:alarm";
};
tv_white {
reg = <2>;
active-low;
label = "white:tv";
};
tel_white {
reg = <3>;
active-low;
label = "white:tel";
};
adsl_white {
reg = <4>;
active-low;
label = "white:adsl";
};
};
Scenario 2 : BCM6368
leds0: led-controller@100000d0 {
compatible = "brcm,bcm6358-leds";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x100000d0 0x8>;
brcm,pol-low;
brcm,clk-div = <4>;
power_red {
reg = <0>;
active-low;
label = "red:power";
};
power_green {
reg = <1>;
active-low;
label = "green:power";
default-state = "on";
};
power_blue {
reg = <2>;
label = "blue:power";
};
broadband_red {
reg = <3>;
active-low;
label = "red:broadband";
};
broadband_green {
reg = <4>;
label = "green:broadband";
};
broadband_blue {
reg = <5>;
active-low;
label = "blue:broadband";
};
wireless_red {
reg = <6>;
active-low;
label = "red:wireless";
};
wireless_green {
reg = <7>;
active-low;
label = "green:wireless";
};
wireless_blue {
reg = <8>;
label = "blue:wireless";
};
phone_red {
reg = <9>;
active-low;
label = "red:phone";
};
phone_green {
reg = <10>;
active-low;
label = "green:phone";
};
phone_blue {
reg = <11>;
label = "blue:phone";
};
upgrading_red {
reg = <12>;
active-low;
label = "red:upgrading";
};
upgrading_green {
reg = <13>;
active-low;
label = "green:upgrading";
};
upgrading_blue {
reg = <14>;
label = "blue:upgrading";
};
};
@@ -45,6 +45,8 @@ properties:
color: true
default-intensity: true
required:
- pwms
- color
@@ -63,12 +65,14 @@ examples:
multi-led {
color = <LED_COLOR_ID_RGB>;
linux,default-trigger = "default-on";
function = LED_FUNCTION_INDICATOR;
max-brightness = <65535>;
led-red {
pwms = <&pwm1 0 1000000>;
color = <LED_COLOR_ID_RED>;
default-intensity = <65535>;
};
led-green {
+4 -5
View File
@@ -16,8 +16,9 @@ in terms of PWM duty-cycle and duration (ms).
To be compatible with the hardware pattern format, maximum 8 tuples of
brightness (PWM) and duration must be written to hw_pattern.
- Brightness range: 0-255
- Min pattern duration: 22 ms
- Max pattern duration: 5660 ms
- Max pattern duration: 5610 ms
The format of the hardware pattern values should be:
"brightness duration brightness duration ..."
@@ -26,9 +27,7 @@ The format of the hardware pattern values should be:
----------------------------
Specify a pattern repeat number, which is common for all channels.
Default is 1; negative numbers and 0 are invalid.
Default is 1. Writing 0 is invalid. Writing -1 or 255 repeats the
pattern indefinitely.
This file will always return the originally written repeat number.
When the 255 value is written to it, all patterns will repeat
indefinitely.
+8
View File
@@ -15451,6 +15451,14 @@ W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml
F: drivers/iio/temperature/ltc2983.c
LTC3220 LED DRIVER
M: Edelweise Escala <edelweise.escala@analog.com>
L: linux-leds@vger.kernel.org
S: Maintained
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/leds/adi,ltc3220.yaml
F: drivers/leds/leds-ltc3220.c
LTC4282 HARDWARE MONITOR DRIVER
M: Nuno Sa <nuno.sa@analog.com>
L: linux-hwmon@vger.kernel.org
+13
View File
@@ -1000,6 +1000,19 @@ config LEDS_ST1202
Say Y to enable support for LEDs connected to LED1202
LED driver chips accessed via the I2C bus.
config LEDS_LTC3220
tristate "LED Driver for Analog Devices Inc. LTC3220"
depends on I2C && LEDS_CLASS
select REGMAP_I2C
help
Say Y to enable support for the Analog Devices LTC3220
18-channel LED controller with I2C interface.
The driver supports individual LED brightness control (64 steps),
hardware-assisted blinking and gradation effects.
To compile this driver as a module, choose M here: the module will
be called leds-ltc3220.
config LEDS_TPS6105X
tristate "LED support for TI TPS6105X"
depends on LEDS_CLASS
+1
View File
@@ -61,6 +61,7 @@ obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o
obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o
obj-$(CONFIG_LEDS_LP8864) += leds-lp8864.o
obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o
obj-$(CONFIG_LEDS_LTC3220) += leds-ltc3220.o
obj-$(CONFIG_LEDS_MAX5970) += leds-max5970.o
obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o
obj-$(CONFIG_LEDS_MAX77705) += leds-max77705.o
+2 -2
View File
@@ -236,8 +236,8 @@ static void bcm63138_leds_create_led(struct bcm63138_leds *leds,
pinctrl = devm_pinctrl_get_select_default(led->cdev.dev);
if (IS_ERR(pinctrl) && PTR_ERR(pinctrl) != -ENODEV) {
dev_warn(led->cdev.dev, "Failed to select %pOF pinctrl: %ld\n",
np, PTR_ERR(pinctrl));
dev_warn(led->cdev.dev, "Failed to select %pOF pinctrl: %pe\n",
np, pinctrl);
}
bit = BIT(led->pin);
+35 -17
View File
@@ -9,8 +9,8 @@
#include <linux/container_of.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/legacy.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/overflow.h>
@@ -211,7 +211,6 @@ static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx,
const struct gpio_led *template)
{
struct gpio_desc *gpiod;
int ret;
/*
* This means the LED does not come from the device tree
@@ -222,16 +221,29 @@ static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx,
gpiod = devm_gpiod_get_index_optional(dev, NULL, idx, GPIOD_OUT_LOW);
if (IS_ERR(gpiod))
return gpiod;
if (gpiod) {
gpiod_set_consumer_name(gpiod, template->name);
return gpiod;
}
/*
* This is the legacy code path for platform code that
* still uses GPIO numbers. Ultimately we would like to get
* rid of this block completely.
*/
gpiod_set_consumer_name(gpiod, template->name);
return gpiod;
}
#ifdef CONFIG_GPIOLIB_LEGACY
/*
* This is the legacy code path for platform code that still uses
* GPIO numbers, mainly MIPS and SuperH board files.
* Ultimately we would like to get rid of this block completely.
*
* ppc44x-warp sets the template->gpiod directly instead of
* adding a lookup table or device properties. This is not
* much better.
*/
static struct gpio_desc *gpio_led_get_legacy_gpiod(struct device *dev, int idx,
const struct gpio_led *template)
{
struct gpio_desc *gpiod;
int ret;
if (template->gpiod)
return template->gpiod;
/* skip leds that aren't available */
if (!gpio_is_valid(template->gpio))
@@ -251,6 +263,13 @@ static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx,
return gpiod;
}
#else
static struct gpio_desc *gpio_led_get_legacy_gpiod(struct device *dev, int idx,
const struct gpio_led *template)
{
return template->gpiod ?: ERR_PTR(-ENOENT);
}
#endif
static int gpio_led_probe(struct platform_device *pdev)
{
@@ -269,14 +288,13 @@ static int gpio_led_probe(struct platform_device *pdev)
const struct gpio_led *template = &pdata->leds[i];
struct gpio_led_data *led_dat = &priv->leds[i];
if (template->gpiod)
led_dat->gpiod = template->gpiod;
else
led_dat->gpiod = gpio_led_get_gpiod(dev, i, template);
if (!led_dat->gpiod)
led_dat->gpiod =
gpio_led_get_gpiod(dev, i, template);
gpio_led_get_legacy_gpiod(dev, i, template);
if (IS_ERR(led_dat->gpiod)) {
dev_info(dev, "Skipping unavailable LED gpio %d (%s)\n",
template->gpio, template->name);
dev_info(dev, "Skipping unavailable LED gpio %s\n",
template->name);
continue;
}
File diff suppressed because it is too large Load Diff
+11 -7
View File
@@ -327,9 +327,9 @@ static int pca9532_gpio_set_value(struct gpio_chip *gc, unsigned int offset,
struct pca9532_led *led = &data->leds[offset];
if (val)
led->state = PCA9532_ON;
else
led->state = PCA9532_OFF;
else
led->state = PCA9532_ON;
pca9532_setled(led);
@@ -349,7 +349,7 @@ static int pca9532_gpio_get_value(struct gpio_chip *gc, unsigned offset)
static int pca9532_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
/* To use as input ensure pin is not driven */
pca9532_gpio_set_value(gc, offset, 0);
pca9532_gpio_set_value(gc, offset, 1);
return 0;
}
@@ -397,10 +397,14 @@ static int pca9532_configure(struct i2c_client *client,
for (i = 0; i < 2; i++) {
data->pwm[i] = pdata->pwm[i];
data->psc[i] = pdata->psc[i];
i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(maxleds, i),
data->pwm[i]);
i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(maxleds, i),
data->psc[i]);
err = i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(maxleds, i),
data->pwm[i]);
if (err < 0)
return err;
err = i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(maxleds, i),
data->psc[i]);
if (err < 0)
return err;
}
data->hw_blink = true;
+63 -39
View File
@@ -31,10 +31,11 @@
#define ST1202_ILED_REG0 0x09
#define ST1202_MAX_LEDS 12
#define ST1202_MAX_PATTERNS 8
#define ST1202_MILLIS_PATTERN_DUR_MAX 5660
#define ST1202_MILLIS_PATTERN_DUR_MAX (ST1202_MILLIS_PATTERN_DUR_MIN * U8_MAX)
#define ST1202_MILLIS_PATTERN_DUR_MIN 22
#define ST1202_PATTERN_DUR 0x16
#define ST1202_PATTERN_PWM 0x1E
#define ST1202_PATTERN_PWM_FULL 0x0FFF
#define ST1202_PATTERN_REP 0x15
struct st1202_led {
@@ -85,7 +86,7 @@ static int st1202_write_reg(struct st1202_chip *chip, int reg, uint8_t val)
static uint8_t st1202_prescalar_to_miliseconds(unsigned int value)
{
return value / ST1202_MILLIS_PATTERN_DUR_MIN - 1;
return value / ST1202_MILLIS_PATTERN_DUR_MIN;
}
static int st1202_pwm_pattern_write(struct st1202_chip *chip, int led_num,
@@ -127,37 +128,11 @@ static int st1202_duration_pattern_write(struct st1202_chip *chip, int pattern,
st1202_prescalar_to_miliseconds(value));
}
static void st1202_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct st1202_led *led = cdev_to_st1202_led(led_cdev);
struct st1202_chip *chip = led->chip;
guard(mutex)(&chip->lock);
st1202_write_reg(chip, ST1202_ILED_REG0 + led->led_num, value);
}
static enum led_brightness st1202_brightness_get(struct led_classdev *led_cdev)
{
struct st1202_led *led = cdev_to_st1202_led(led_cdev);
struct st1202_chip *chip = led->chip;
u8 value = 0;
guard(mutex)(&chip->lock);
st1202_read_reg(chip, ST1202_ILED_REG0 + led->led_num, &value);
return value;
}
static int st1202_channel_set(struct st1202_chip *chip, int led_num, bool active)
static int __st1202_channel_set(struct st1202_chip *chip, int led_num, bool active)
{
u8 chan_low, chan_high;
int ret;
guard(mutex)(&chip->lock);
if (led_num <= 7) {
ret = st1202_read_reg(chip, ST1202_CHAN_ENABLE_LOW, &chan_low);
if (ret < 0)
@@ -185,6 +160,40 @@ static int st1202_channel_set(struct st1202_chip *chip, int led_num, bool active
return 0;
}
static int st1202_channel_set(struct st1202_chip *chip, int led_num, bool active)
{
guard(mutex)(&chip->lock);
return __st1202_channel_set(chip, led_num, active);
}
static void st1202_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct st1202_led *led = cdev_to_st1202_led(led_cdev);
struct st1202_chip *chip = led->chip;
guard(mutex)(&chip->lock);
for (int patt = 0; patt < ST1202_MAX_PATTERNS; patt++)
st1202_pwm_pattern_write(chip, led->led_num, patt, ST1202_PATTERN_PWM_FULL);
st1202_write_reg(chip, ST1202_ILED_REG0 + led->led_num, value);
__st1202_channel_set(chip, led->led_num, !!value);
}
static enum led_brightness st1202_brightness_get(struct led_classdev *led_cdev)
{
struct st1202_led *led = cdev_to_st1202_led(led_cdev);
struct st1202_chip *chip = led->chip;
u8 value = 0;
guard(mutex)(&chip->lock);
st1202_read_reg(chip, ST1202_ILED_REG0 + led->led_num, &value);
return value;
}
static int st1202_led_set(struct led_classdev *ldev, enum led_brightness value)
{
struct st1202_led *led = cdev_to_st1202_led(ldev);
@@ -200,12 +209,16 @@ static int st1202_led_pattern_clear(struct led_classdev *ldev)
guard(mutex)(&chip->lock);
ret = st1202_write_reg(chip, ST1202_CONFIG_REG, ST1202_CONFIG_REG_SHFT);
if (ret != 0)
return ret;
for (int patt = 0; patt < ST1202_MAX_PATTERNS; patt++) {
ret = st1202_pwm_pattern_write(chip, led->led_num, patt, LED_OFF);
ret = st1202_pwm_pattern_write(chip, led->led_num, patt, ST1202_PATTERN_PWM_FULL);
if (ret != 0)
return ret;
ret = st1202_duration_pattern_write(chip, patt, ST1202_MILLIS_PATTERN_DUR_MIN);
ret = st1202_write_reg(chip, ST1202_PATTERN_DUR + patt, 0);
if (ret != 0)
return ret;
}
@@ -224,13 +237,19 @@ static int st1202_led_pattern_set(struct led_classdev *ldev,
if (len > ST1202_MAX_PATTERNS)
return -EINVAL;
guard(mutex)(&chip->lock);
for (int patt = 0; patt < len; patt++) {
if (pattern[patt].delta_t < ST1202_MILLIS_PATTERN_DUR_MIN ||
pattern[patt].delta_t > ST1202_MILLIS_PATTERN_DUR_MAX)
return -EINVAL;
}
guard(mutex)(&chip->lock);
ret = st1202_write_reg(chip, ST1202_CONFIG_REG, ST1202_CONFIG_REG_SHFT);
if (ret != 0)
return ret;
for (int patt = 0; patt < len; patt++) {
ret = st1202_pwm_pattern_write(chip, led->led_num, patt, pattern[patt].brightness);
if (ret != 0)
return ret;
@@ -244,6 +263,10 @@ static int st1202_led_pattern_set(struct led_classdev *ldev,
if (ret != 0)
return ret;
ret = __st1202_channel_set(chip, led->led_num, true);
if (ret != 0)
return ret;
ret = st1202_write_reg(chip, ST1202_CONFIG_REG, (ST1202_CONFIG_REG_PATSR |
ST1202_CONFIG_REG_PATS | ST1202_CONFIG_REG_SHFT));
if (ret != 0)
@@ -256,13 +279,19 @@ static int st1202_dt_init(struct st1202_chip *chip)
{
struct device *dev = &chip->client->dev;
struct st1202_led *led;
int err, reg;
int err;
u32 reg;
for_each_available_child_of_node_scoped(dev_of_node(dev), child) {
err = of_property_read_u32(child, "reg", &reg);
if (err)
return dev_err_probe(dev, err, "Invalid register\n");
if (reg >= ST1202_MAX_LEDS)
return dev_err_probe(dev, -EINVAL,
"LED reg %u out of range [0, %d]\n",
reg, ST1202_MAX_LEDS - 1);
led = &chip->leds[reg];
led->is_active = true;
led->fwnode = of_fwnode_handle(child);
@@ -322,11 +351,6 @@ static int st1202_setup(struct st1202_chip *chip)
if (ret < 0)
return ret;
ret = st1202_write_reg(chip, ST1202_CONFIG_REG,
ST1202_CONFIG_REG_PATS | ST1202_CONFIG_REG_PATSR);
if (ret < 0)
return ret;
return 0;
}
+1 -2
View File
@@ -204,9 +204,9 @@ int lp5860_device_init(struct device *dev)
mutex_lock(&lp->lock);
ret = regmap_update_bits(lp->regmap, LP5860_REG_DEV_INITIAL, LP5860_MODE_MASK,
LP5860_MODE_1 << LP5860_MODE_SHIFT);
mutex_unlock(&lp->lock);
if (ret)
goto err_disable;
mutex_unlock(&lp->lock);
ret = lp5860_init_dt(lp);
if (ret)
@@ -215,7 +215,6 @@ int lp5860_device_init(struct device *dev)
return 0;
err_disable:
mutex_unlock(&lp->lock);
lp5860_chip_enable(lp, LP5860_CHIP_DISABLE);
return ret;
}
+5 -5
View File
@@ -38,6 +38,7 @@ static int lp5860_probe(struct spi_device *spi)
struct device *dev = &spi->dev;
struct lp5860 *lp5860;
unsigned int multi_leds;
int ret;
multi_leds = device_get_child_node_count(dev);
if (!multi_leds) {
@@ -61,7 +62,10 @@ static int lp5860_probe(struct spi_device *spi)
"Failed to initialise Regmap.\n");
lp5860->dev = dev;
mutex_init(&lp5860->lock);
ret = devm_mutex_init(dev, &lp5860->lock);
if (ret)
return ret;
spi_set_drvdata(spi, lp5860);
@@ -70,10 +74,6 @@ static int lp5860_probe(struct spi_device *spi)
static void lp5860_remove(struct spi_device *spi)
{
struct lp5860 *lp5860 = spi_get_drvdata(spi);
mutex_destroy(&lp5860->lock);
lp5860_device_remove(&spi->dev);
}
+2
View File
@@ -94,6 +94,8 @@ static int iterate_subleds(struct device *dev, struct pwm_mc_led *priv,
}
subled[priv->mc_cdev.num_colors].color_index = color;
fwnode_property_read_u32(fwnode, "default-intensity",
&subled[priv->mc_cdev.num_colors].intensity);
priv->mc_cdev.num_colors++;
}
+45 -1
View File
@@ -129,6 +129,22 @@ static void set_baseline_state(struct led_netdev_data *trigger_data)
trigger_data->link_speed == SPEED_10000)
blink_on = true;
if (test_bit(TRIGGER_NETDEV_LINK_25000, &trigger_data->mode) &&
trigger_data->link_speed == SPEED_25000)
blink_on = true;
if (test_bit(TRIGGER_NETDEV_LINK_40000, &trigger_data->mode) &&
trigger_data->link_speed == SPEED_40000)
blink_on = true;
if (test_bit(TRIGGER_NETDEV_LINK_50000, &trigger_data->mode) &&
trigger_data->link_speed == SPEED_50000)
blink_on = true;
if (test_bit(TRIGGER_NETDEV_LINK_100000, &trigger_data->mode) &&
trigger_data->link_speed == SPEED_100000)
blink_on = true;
if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) &&
trigger_data->duplex == DUPLEX_HALF)
blink_on = true;
@@ -342,6 +358,10 @@ static ssize_t netdev_led_attr_show(struct device *dev, char *buf,
case TRIGGER_NETDEV_LINK_2500:
case TRIGGER_NETDEV_LINK_5000:
case TRIGGER_NETDEV_LINK_10000:
case TRIGGER_NETDEV_LINK_25000:
case TRIGGER_NETDEV_LINK_40000:
case TRIGGER_NETDEV_LINK_50000:
case TRIGGER_NETDEV_LINK_100000:
case TRIGGER_NETDEV_HALF_DUPLEX:
case TRIGGER_NETDEV_FULL_DUPLEX:
case TRIGGER_NETDEV_TX:
@@ -378,6 +398,10 @@ static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
case TRIGGER_NETDEV_LINK_2500:
case TRIGGER_NETDEV_LINK_5000:
case TRIGGER_NETDEV_LINK_10000:
case TRIGGER_NETDEV_LINK_25000:
case TRIGGER_NETDEV_LINK_40000:
case TRIGGER_NETDEV_LINK_50000:
case TRIGGER_NETDEV_LINK_100000:
case TRIGGER_NETDEV_HALF_DUPLEX:
case TRIGGER_NETDEV_FULL_DUPLEX:
case TRIGGER_NETDEV_TX:
@@ -401,7 +425,11 @@ static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
test_bit(TRIGGER_NETDEV_LINK_1000, &mode) ||
test_bit(TRIGGER_NETDEV_LINK_2500, &mode) ||
test_bit(TRIGGER_NETDEV_LINK_5000, &mode) ||
test_bit(TRIGGER_NETDEV_LINK_10000, &mode)))
test_bit(TRIGGER_NETDEV_LINK_10000, &mode) ||
test_bit(TRIGGER_NETDEV_LINK_25000, &mode) ||
test_bit(TRIGGER_NETDEV_LINK_40000, &mode) ||
test_bit(TRIGGER_NETDEV_LINK_50000, &mode) ||
test_bit(TRIGGER_NETDEV_LINK_100000, &mode)))
return -EINVAL;
cancel_delayed_work_sync(&trigger_data->work);
@@ -438,6 +466,10 @@ DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000);
DEFINE_NETDEV_TRIGGER(link_2500, TRIGGER_NETDEV_LINK_2500);
DEFINE_NETDEV_TRIGGER(link_5000, TRIGGER_NETDEV_LINK_5000);
DEFINE_NETDEV_TRIGGER(link_10000, TRIGGER_NETDEV_LINK_10000);
DEFINE_NETDEV_TRIGGER(link_25000, TRIGGER_NETDEV_LINK_25000);
DEFINE_NETDEV_TRIGGER(link_40000, TRIGGER_NETDEV_LINK_40000);
DEFINE_NETDEV_TRIGGER(link_50000, TRIGGER_NETDEV_LINK_50000);
DEFINE_NETDEV_TRIGGER(link_100000, TRIGGER_NETDEV_LINK_100000);
DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX);
DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX);
DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX);
@@ -526,6 +558,10 @@ static umode_t netdev_trig_link_speed_visible(struct kobject *kobj,
CHECK_LINK_MODE_ATTR(2500);
CHECK_LINK_MODE_ATTR(5000);
CHECK_LINK_MODE_ATTR(10000);
CHECK_LINK_MODE_ATTR(25000);
CHECK_LINK_MODE_ATTR(40000);
CHECK_LINK_MODE_ATTR(50000);
CHECK_LINK_MODE_ATTR(100000);
}
return 0;
@@ -538,6 +574,10 @@ static struct attribute *netdev_trig_link_speed_attrs[] = {
&dev_attr_link_2500.attr,
&dev_attr_link_5000.attr,
&dev_attr_link_10000.attr,
&dev_attr_link_25000.attr,
&dev_attr_link_40000.attr,
&dev_attr_link_50000.attr,
&dev_attr_link_100000.attr,
NULL
};
@@ -673,6 +713,10 @@ static void netdev_trig_work(struct work_struct *work)
test_bit(TRIGGER_NETDEV_LINK_2500, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_LINK_5000, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_LINK_10000, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_LINK_25000, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_LINK_40000, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_LINK_50000, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_LINK_100000, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode);
interval = jiffies_to_msecs(
+6
View File
@@ -607,6 +607,10 @@ enum led_trigger_netdev_modes {
TRIGGER_NETDEV_LINK_2500,
TRIGGER_NETDEV_LINK_5000,
TRIGGER_NETDEV_LINK_10000,
TRIGGER_NETDEV_LINK_25000,
TRIGGER_NETDEV_LINK_40000,
TRIGGER_NETDEV_LINK_50000,
TRIGGER_NETDEV_LINK_100000,
TRIGGER_NETDEV_HALF_DUPLEX,
TRIGGER_NETDEV_FULL_DUPLEX,
TRIGGER_NETDEV_TX,
@@ -676,8 +680,10 @@ typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state,
struct gpio_led {
const char *name;
const char *default_trigger;
#ifdef CONFIG_GPIOLIB_LEGACY
unsigned gpio;
unsigned active_low : 1;
#endif
unsigned retain_state_suspended : 1;
unsigned panic_indicator : 1;
unsigned default_state : 2;