Merge tag 'leds-next-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds
Pull LED updates from Lee Jones:
"Improvements & Fixes:
- A fix for QCOM Flash to prevent incorrect register access when the
driver is re-bound. This is solved by duplicating a static register
array during the probe function, which prevents register addresses
from being miscalculated after multiple binds
- The LP50xx driver now correctly handles the 'reg' property in
device tree child nodes to ensure the multi_index is set correctly.
This prevents issues where LEDs could be controlled incorrectly if
the device tree nodes were processed in a different order. An error
is returned if the reg property is missing or out of range
- Add a Kconfig dependency on between TPS6131x and
V4L2_FLASH_LED_CLASS to prevent a build failure when the driver is
built-in and the V4L2 flash infrastructure is a loadable module
- Fix a potential buffer overflow warning in PCA955x reported by
older GCC versions by using a more precise format specifier when
creating the default LED label.
Cleanups & Refactoring:
- Correct the MAINTAINERS file entry for the TPS6131X flash LED
driver to point to the correct device tree binding file name
- Fix a comment in the Flash Class for the flash_timeout setter to
"flash timeout" from "flash duration" for accuracy
- The of_led_get() function is no longer exported as it has no users
outside of its own module.
Removals:
- Revert the commit to configure LED blink intervals for hardware
offload in the Netdev Trigger. This change was found to break
existing PHY drivers by putting their LEDs into a permanent,
unconditional blinking state.
Device Tree Bindings Updates:
- Update the binding for LP50xx to document that the child reg
property is the index within the LED bank. The example was also
updated to use correct values
- Update the JNCP5623 binding to add 0x39 as a valid I2C address, as
it is used by the NCP5623C variant"
* tag 'leds-next-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds:
dt-bindings: leds: ncp5623: Add 0x39 as a valid I2C address
Revert "leds: trigger: netdev: Configure LED blink interval for HW offload"
leds: pca955x: Avoid potential overflow when filling default_label (take 2)
leds: Unexport of_led_get()
leds: tps6131x: Add V4L2_FLASH_LED_CLASS dependency
dt-bindings: leds: lp50xx: Document child reg, fix example
leds: leds-lp50xx: Handle reg to get correct multi_index
leds: led-class-flash:: Fix flash_timeout comment
MAINTAINERS: Adjust file entry in TPS6131X FLASH LED DRIVER
leds: flash: leds-qcom-flash: Fix registry access after re-bind
This commit is contained in:
@@ -81,7 +81,12 @@ patternProperties:
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
items:
|
||||
- minimum: 0
|
||||
maximum: 2
|
||||
|
||||
description:
|
||||
This property denotes the index within the LED bank.
|
||||
|
||||
required:
|
||||
- reg
|
||||
@@ -138,18 +143,18 @@ examples:
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_STANDBY;
|
||||
|
||||
led@3 {
|
||||
reg = <0x3>;
|
||||
led@0 {
|
||||
reg = <0x0>;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
};
|
||||
|
||||
led@4 {
|
||||
reg = <0x4>;
|
||||
led@1 {
|
||||
reg = <0x1>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
};
|
||||
|
||||
led@5 {
|
||||
reg = <0x5>;
|
||||
led@2 {
|
||||
reg = <0x2>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -19,7 +19,9 @@ properties:
|
||||
- onnn,ncp5623
|
||||
|
||||
reg:
|
||||
const: 0x38
|
||||
enum:
|
||||
- 0x38
|
||||
- 0x39
|
||||
|
||||
multi-led:
|
||||
type: object
|
||||
|
||||
+1
-1
@@ -24813,7 +24813,7 @@ TEXAS INSTRUMENTS TPS6131X FLASH LED DRIVER
|
||||
M: Matthias Fend <matthias.fend@emfend.at>
|
||||
L: linux-leds@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/leds/ti,tps6131x.yaml
|
||||
F: Documentation/devicetree/bindings/leds/ti,tps61310.yaml
|
||||
F: drivers/leds/flash/leds-tps6131x.c
|
||||
|
||||
TEXAS INSTRUMENTS' DAC7612 DAC DRIVER
|
||||
|
||||
@@ -136,6 +136,7 @@ config LEDS_TPS6131X
|
||||
tristate "LED support for TI TPS6131x flash LED driver"
|
||||
depends on I2C && OF
|
||||
depends on GPIOLIB
|
||||
depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This option enables support for Texas Instruments TPS61310/TPS61311
|
||||
|
||||
@@ -117,7 +117,7 @@ enum {
|
||||
REG_MAX_COUNT,
|
||||
};
|
||||
|
||||
static struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = {
|
||||
static const struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = {
|
||||
REG_FIELD(0x08, 0, 7), /* status1 */
|
||||
REG_FIELD(0x09, 0, 7), /* status2 */
|
||||
REG_FIELD(0x0a, 0, 7), /* status3 */
|
||||
@@ -132,7 +132,7 @@ static struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = {
|
||||
REG_FIELD(0x58, 0, 2), /* therm_thrsh3 */
|
||||
};
|
||||
|
||||
static struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = {
|
||||
static const struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = {
|
||||
REG_FIELD(0x06, 0, 7), /* status1 */
|
||||
REG_FIELD(0x07, 0, 6), /* status2 */
|
||||
REG_FIELD(0x09, 0, 7), /* status3 */
|
||||
@@ -854,11 +854,17 @@ static int qcom_flash_led_probe(struct platform_device *pdev)
|
||||
if (val == FLASH_SUBTYPE_3CH_PM8150_VAL || val == FLASH_SUBTYPE_3CH_PMI8998_VAL) {
|
||||
flash_data->hw_type = QCOM_MVFLASH_3CH;
|
||||
flash_data->max_channels = 3;
|
||||
regs = mvflash_3ch_regs;
|
||||
regs = devm_kmemdup(dev, mvflash_3ch_regs, sizeof(mvflash_3ch_regs),
|
||||
GFP_KERNEL);
|
||||
if (!regs)
|
||||
return -ENOMEM;
|
||||
} else if (val == FLASH_SUBTYPE_4CH_VAL) {
|
||||
flash_data->hw_type = QCOM_MVFLASH_4CH;
|
||||
flash_data->max_channels = 4;
|
||||
regs = mvflash_4ch_regs;
|
||||
regs = devm_kmemdup(dev, mvflash_4ch_regs, sizeof(mvflash_4ch_regs),
|
||||
GFP_KERNEL);
|
||||
if (!regs)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = regmap_read(regmap, reg_base + FLASH_REVISION_REG, &val);
|
||||
if (rc < 0) {
|
||||
@@ -880,6 +886,7 @@ static int qcom_flash_led_probe(struct platform_device *pdev)
|
||||
dev_err(dev, "Failed to allocate regmap field, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
devm_kfree(dev, regs); /* devm_regmap_field_bulk_alloc() makes copies */
|
||||
|
||||
platform_set_drvdata(pdev, flash_data);
|
||||
mutex_init(&flash_data->lock);
|
||||
|
||||
@@ -256,7 +256,7 @@ static const struct class leds_class = {
|
||||
* Returns the LED device parsed from the phandle specified in the "leds"
|
||||
* property of a device tree node or a negative error-code on failure.
|
||||
*/
|
||||
struct led_classdev *of_led_get(struct device_node *np, int index)
|
||||
static struct led_classdev *of_led_get(struct device_node *np, int index)
|
||||
{
|
||||
struct device *led_dev;
|
||||
struct device_node *led_node;
|
||||
@@ -270,7 +270,6 @@ struct led_classdev *of_led_get(struct device_node *np, int index)
|
||||
|
||||
return led_module_get(led_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_led_get);
|
||||
|
||||
/**
|
||||
* led_put() - release a LED device
|
||||
|
||||
@@ -476,6 +476,7 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
|
||||
return -ENOMEM;
|
||||
|
||||
fwnode_for_each_child_node(child, led_node) {
|
||||
int multi_index;
|
||||
ret = fwnode_property_read_u32(led_node, "color",
|
||||
&color_id);
|
||||
if (ret) {
|
||||
@@ -483,8 +484,16 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
|
||||
dev_err(priv->dev, "Cannot read color\n");
|
||||
return ret;
|
||||
}
|
||||
ret = fwnode_property_read_u32(led_node, "reg", &multi_index);
|
||||
if (ret != 0) {
|
||||
dev_err(priv->dev, "reg must be set\n");
|
||||
return -EINVAL;
|
||||
} else if (multi_index >= LP50XX_LEDS_PER_MODULE) {
|
||||
dev_err(priv->dev, "reg %i out of range\n", multi_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mc_led_info[num_colors].color_index = color_id;
|
||||
mc_led_info[multi_index].color_index = color_id;
|
||||
num_colors++;
|
||||
}
|
||||
|
||||
|
||||
@@ -587,7 +587,7 @@ static int pca955x_probe(struct i2c_client *client)
|
||||
struct pca955x_platform_data *pdata;
|
||||
bool keep_psc0 = false;
|
||||
bool set_default_label = false;
|
||||
char default_label[8];
|
||||
char default_label[4];
|
||||
int bit, err, reg;
|
||||
|
||||
chip = i2c_get_match_data(client);
|
||||
@@ -693,7 +693,7 @@ static int pca955x_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
if (set_default_label) {
|
||||
snprintf(default_label, sizeof(default_label), "%u", i);
|
||||
snprintf(default_label, sizeof(default_label), "%hhu", i);
|
||||
init_data.default_label = default_label;
|
||||
} else {
|
||||
init_data.default_label = NULL;
|
||||
|
||||
@@ -68,7 +68,6 @@ struct led_netdev_data {
|
||||
unsigned int last_activity;
|
||||
|
||||
unsigned long mode;
|
||||
unsigned long blink_delay;
|
||||
int link_speed;
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported_link_modes);
|
||||
u8 duplex;
|
||||
@@ -87,10 +86,6 @@ static void set_baseline_state(struct led_netdev_data *trigger_data)
|
||||
/* Already validated, hw control is possible with the requested mode */
|
||||
if (trigger_data->hw_control) {
|
||||
led_cdev->hw_control_set(led_cdev, trigger_data->mode);
|
||||
if (led_cdev->blink_set) {
|
||||
led_cdev->blink_set(led_cdev, &trigger_data->blink_delay,
|
||||
&trigger_data->blink_delay);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -459,11 +454,10 @@ static ssize_t interval_store(struct device *dev,
|
||||
size_t size)
|
||||
{
|
||||
struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
|
||||
struct led_classdev *led_cdev = trigger_data->led_cdev;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
if (trigger_data->hw_control && !led_cdev->blink_set)
|
||||
if (trigger_data->hw_control)
|
||||
return -EINVAL;
|
||||
|
||||
ret = kstrtoul(buf, 0, &value);
|
||||
@@ -472,13 +466,9 @@ static ssize_t interval_store(struct device *dev,
|
||||
|
||||
/* impose some basic bounds on the timer interval */
|
||||
if (value >= 5 && value <= 10000) {
|
||||
if (trigger_data->hw_control) {
|
||||
trigger_data->blink_delay = value;
|
||||
} else {
|
||||
cancel_delayed_work_sync(&trigger_data->work);
|
||||
cancel_delayed_work_sync(&trigger_data->work);
|
||||
|
||||
atomic_set(&trigger_data->interval, msecs_to_jiffies(value));
|
||||
}
|
||||
atomic_set(&trigger_data->interval, msecs_to_jiffies(value));
|
||||
set_baseline_state(trigger_data); /* resets timer */
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ int led_update_flash_brightness(struct led_classdev_flash *fled_cdev);
|
||||
* @fled_cdev: the flash LED to set
|
||||
* @timeout: the flash timeout to set it to
|
||||
*
|
||||
* Set the flash strobe duration.
|
||||
* Set the flash strobe timeout.
|
||||
*
|
||||
* Returns: 0 on success or negative error value on failure
|
||||
*/
|
||||
|
||||
@@ -294,7 +294,6 @@ void led_remove_lookup(struct led_lookup_data *led_lookup);
|
||||
struct led_classdev *__must_check led_get(struct device *dev, char *con_id);
|
||||
struct led_classdev *__must_check devm_led_get(struct device *dev, char *con_id);
|
||||
|
||||
extern struct led_classdev *of_led_get(struct device_node *np, int index);
|
||||
extern void led_put(struct led_classdev *led_cdev);
|
||||
struct led_classdev *__must_check devm_of_led_get(struct device *dev,
|
||||
int index);
|
||||
|
||||
Reference in New Issue
Block a user