Commit 431f1051 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'leds-next-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds

Pull LED updates from Lee Jones:
 "Core Frameworks:
   - Add support for a bunch more colours

  New Drivers:
   - Add support for Kinetic KTD2026/7 RGB/White LEDs

  New Functionality:
   - Add support for device to enter HW Controlled Mode to Turris Omnia
     LEDs
   - Add support for HW Gamma Correction to Turris Omnia LEDs

  Fix-ups:
   - Apply new __counted_by() annotation to several data structures
     containing flexible arrays
   - Rid the return value from Platform's .remove() operation
   - Use *_cansleep() variants for instances were threads can sleep
   - Improve the semantics when setting the brightness
   - Generic clean-ups; code reduction, coding style, standard patterns
   - Replace strncpy() with strscpy()
   - Fix-up / add various documentation
   - Re-author the GPIO associated Trigger to use trigger-sources
   - Move to using standard APIs and helpers
   - Improve error checking
   - Stop using static GPIO bases

  Bug Fixes:
   - Fix Pointer to Enum casing warnings
   - Do not pretend that I2C backed device supports SMBUS
   - Ensure PWM LEDs are extinguished when disabled, rather than held in
     a state
   - Fix 'output may be truncated' warnings"

* tag 'leds-next-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds: (43 commits)
  leds: lp5521: Add an error check in lp5521_post_init_device
  leds: gpio: Update headers
  leds: gpio: Remove unneeded assignment
  leds: gpio: Move temporary variable for struct device to gpio_led_probe()
  leds: gpio: Refactor code to use devm_gpiod_get_index_optional()
  leds: gpio: Utilise PTR_ERR_OR_ZERO()
  leds: gpio: Keep driver firmware interface agnostic
  leds: core: Refactor led_update_brightness() to use standard pattern
  leds: turris-omnia: Fix brightness setting and trigger activating
  leds: sc27xx: Move mutex_init() down
  leds: trigger: netdev: Move size check in set_device_name
  leds: Add ktd202x driver
  dt-bindings: leds: Add Kinetic KTD2026/2027 LED
  leds: core: Add more colors from DT bindings to led_colors
  dt-bindings: leds: Last color ID is now 14 (LED_COLOR_ID_LIME)
  leds: tca6507: Don't use fixed GPIO base
  leds: lp3952: Convert to use maple tree register cache
  leds: lm392x: Convert to use maple tree register cache
  leds: aw200xx: Convert to use maple tree register cache
  leds: lm3601x: Convert to use maple tree register cache
  ...
parents 38984d78 b9604be2
......@@ -12,3 +12,17 @@ Description: (RW) On the front panel of the Turris Omnia router there is also
able to change this setting from software.
Format: %i
What: /sys/class/leds/<led>/device/gamma_correction
Date: August 2023
KernelVersion: 6.6
Contact: Marek Behún <kabel@kernel.org>
Description: (RW) Newer versions of the microcontroller firmware of the
Turris Omnia router support gamma correction for the RGB LEDs.
This feature can be enabled/disabled by writing to this file.
If the feature is not supported because the MCU firmware is too
old, the file always reads as 0, and writing to the file results
in the EOPNOTSUPP error.
Format: %i
......@@ -43,7 +43,7 @@ properties:
LED_COLOR_ID available, add a new one.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 9
maximum: 14
function-enumerator:
description:
......@@ -191,6 +191,8 @@ properties:
each of them having its own LED assigned (assuming they are not
hardwired). In such cases this property should contain phandle(s) of
related source device(s).
Another example is a GPIO line that will be monitored and mirror the
state of the line (with or without inversion flags) to the LED.
In many cases LED can be related to more than one device (e.g. one USB LED
vs. multiple USB ports). Each source should be represented by a node in
the device tree and be referenced by a phandle and a set of phandle
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/leds/kinetic,ktd202x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Kinetic KTD2026/7 RGB/White LED Driver
maintainers:
- André Apitzsch <git@apitzsch.eu>
description: |
The KTD2026/7 is a RGB/White LED driver with I2C interface.
The data sheet can be found at:
https://www.kinet-ic.com/uploads/KTD2026-7-04h.pdf
properties:
compatible:
enum:
- kinetic,ktd2026
- kinetic,ktd2027
reg:
maxItems: 1
vin-supply:
description: Regulator providing power to the "VIN" pin.
vio-supply:
description: Regulator providing power for pull-up of the I/O lines.
Note that this regulator does not directly connect to KTD2026, but is
needed for the correct operation of the status ("ST") and I2C lines.
"#address-cells":
const: 1
"#size-cells":
const: 0
multi-led:
type: object
$ref: leds-class-multicolor.yaml#
unevaluatedProperties: false
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"^led@[0-3]$":
type: object
$ref: common.yaml#
unevaluatedProperties: false
properties:
reg:
description: Index of the LED.
minimum: 0
maximum: 3
required:
- reg
- color
required:
- "#address-cells"
- "#size-cells"
patternProperties:
"^led@[0-3]$":
type: object
$ref: common.yaml#
unevaluatedProperties: false
properties:
reg:
description: Index of the LED.
minimum: 0
maximum: 3
required:
- reg
required:
- compatible
- reg
- "#address-cells"
- "#size-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/leds/common.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
led-controller@30 {
compatible = "kinetic,ktd2026";
reg = <0x30>;
#address-cells = <1>;
#size-cells = <0>;
vin-supply = <&pm8916_l17>;
vio-supply = <&pm8916_l6>;
led@0 {
reg = <0>;
function = LED_FUNCTION_STATUS;
color = <LED_COLOR_ID_RED>;
};
led@1 {
reg = <1>;
function = LED_FUNCTION_STATUS;
color = <LED_COLOR_ID_GREEN>;
};
led@2 {
reg = <2>;
function = LED_FUNCTION_STATUS;
color = <LED_COLOR_ID_BLUE>;
};
};
};
- |
#include <dt-bindings/leds/common.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
led-controller@30 {
compatible = "kinetic,ktd2026";
reg = <0x30>;
#address-cells = <1>;
#size-cells = <0>;
vin-supply = <&pm8916_l17>;
vio-supply = <&pm8916_l6>;
multi-led {
color = <LED_COLOR_ID_RGB>;
function = LED_FUNCTION_STATUS;
#address-cells = <1>;
#size-cells = <0>;
led@0 {
reg = <0>;
color = <LED_COLOR_ID_RED>;
};
led@1 {
reg = <1>;
color = <LED_COLOR_ID_GREEN>;
};
led@2 {
reg = <2>;
color = <LED_COLOR_ID_BLUE>;
};
};
};
};
......@@ -187,6 +187,7 @@ config LEDS_TURRIS_OMNIA
depends on I2C
depends on MACH_ARMADA_38X || COMPILE_TEST
depends on OF
select LEDS_TRIGGERS
help
This option enables basic support for the LEDs found on the front
side of CZ.NIC's Turris Omnia router. There are 12 RGB LEDs on the
......
......@@ -837,7 +837,7 @@ static int intel_sso_led_probe(struct platform_device *pdev)
return 0;
}
static int intel_sso_led_remove(struct platform_device *pdev)
static void intel_sso_led_remove(struct platform_device *pdev)
{
struct sso_led_priv *priv;
struct sso_led *led, *n;
......@@ -850,8 +850,6 @@ static int intel_sso_led_remove(struct platform_device *pdev)
}
regmap_exit(priv->mmap);
return 0;
}
static const struct of_device_id of_sso_led_match[] = {
......@@ -863,7 +861,7 @@ MODULE_DEVICE_TABLE(of, of_sso_led_match);
static struct platform_driver intel_sso_led_driver = {
.probe = intel_sso_led_probe,
.remove = intel_sso_led_remove,
.remove_new = intel_sso_led_remove,
.driver = {
.name = "lgm-ssoled",
.of_match_table = of_sso_led_match,
......
......@@ -522,7 +522,7 @@ static int aat1290_led_probe(struct platform_device *pdev)
return ret;
}
static int aat1290_led_remove(struct platform_device *pdev)
static void aat1290_led_remove(struct platform_device *pdev)
{
struct aat1290_led *led = platform_get_drvdata(pdev);
......@@ -530,8 +530,6 @@ static int aat1290_led_remove(struct platform_device *pdev)
led_classdev_flash_unregister(&led->fled_cdev);
mutex_destroy(&led->lock);
return 0;
}
static const struct of_device_id aat1290_led_dt_match[] = {
......@@ -542,7 +540,7 @@ MODULE_DEVICE_TABLE(of, aat1290_led_dt_match);
static struct platform_driver aat1290_led_driver = {
.probe = aat1290_led_probe,
.remove = aat1290_led_remove,
.remove_new = aat1290_led_remove,
.driver = {
.name = "aat1290",
.of_match_table = aat1290_led_dt_match,
......
......@@ -386,15 +386,13 @@ static int ktd2692_probe(struct platform_device *pdev)
return 0;
}
static int ktd2692_remove(struct platform_device *pdev)
static void ktd2692_remove(struct platform_device *pdev)
{
struct ktd2692_context *led = platform_get_drvdata(pdev);
led_classdev_flash_unregister(&led->fled_cdev);
mutex_destroy(&led->lock);
return 0;
}
static const struct of_device_id ktd2692_match[] = {
......@@ -409,7 +407,7 @@ static struct platform_driver ktd2692_driver = {
.of_match_table = ktd2692_match,
},
.probe = ktd2692_probe,
.remove = ktd2692_remove,
.remove_new = ktd2692_remove,
};
module_platform_driver(ktd2692_driver);
......
......@@ -123,7 +123,7 @@ static const struct regmap_config lm3601x_regmap = {
.max_register = LM3601X_DEV_ID_REG,
.reg_defaults = lm3601x_regmap_defs,
.num_reg_defaults = ARRAY_SIZE(lm3601x_regmap_defs),
.cache_type = REGCACHE_RBTREE,
.cache_type = REGCACHE_MAPLE,
.volatile_reg = lm3601x_volatile_reg,
};
......
......@@ -1016,7 +1016,7 @@ static int max77693_led_probe(struct platform_device *pdev)
return ret;
}
static int max77693_led_remove(struct platform_device *pdev)
static void max77693_led_remove(struct platform_device *pdev)
{
struct max77693_led_device *led = platform_get_drvdata(pdev);
struct max77693_sub_led *sub_leds = led->sub_leds;
......@@ -1032,8 +1032,6 @@ static int max77693_led_remove(struct platform_device *pdev)
}
mutex_destroy(&led->lock);
return 0;
}
static const struct of_device_id max77693_led_dt_match[] = {
......@@ -1044,7 +1042,7 @@ MODULE_DEVICE_TABLE(of, max77693_led_dt_match);
static struct platform_driver max77693_led_driver = {
.probe = max77693_led_probe,
.remove = max77693_led_remove,
.remove_new = max77693_led_remove,
.driver = {
.name = "max77693-led",
.of_match_table = max77693_led_dt_match,
......
......@@ -91,7 +91,7 @@ struct mt6360_priv {
unsigned int fled_torch_used;
unsigned int leds_active;
unsigned int leds_count;
struct mt6360_led leds[];
struct mt6360_led leds[] __counted_by(leds_count);
};
static int mt6360_mc_brightness_set(struct led_classdev *lcdev,
......@@ -855,12 +855,11 @@ static int mt6360_led_probe(struct platform_device *pdev)
return ret;
}
static int mt6360_led_remove(struct platform_device *pdev)
static void mt6360_led_remove(struct platform_device *pdev)
{
struct mt6360_priv *priv = platform_get_drvdata(pdev);
mt6360_v4l2_flash_release(priv);
return 0;
}
static const struct of_device_id __maybe_unused mt6360_led_of_id[] = {
......@@ -875,7 +874,7 @@ static struct platform_driver mt6360_led_driver = {
.of_match_table = mt6360_led_of_id,
},
.probe = mt6360_led_probe,
.remove = mt6360_led_remove,
.remove_new = mt6360_led_remove,
};
module_platform_driver(mt6360_led_driver);
......
......@@ -81,7 +81,7 @@ struct mt6370_priv {
unsigned int fled_torch_used;
unsigned int leds_active;
unsigned int leds_count;
struct mt6370_led leds[];
struct mt6370_led leds[] __counted_by(leds_count);
};
static int mt6370_torch_brightness_set(struct led_classdev *lcdev, enum led_brightness level)
......
......@@ -755,7 +755,7 @@ static int qcom_flash_led_probe(struct platform_device *pdev)
return rc;
}
static int qcom_flash_led_remove(struct platform_device *pdev)
static void qcom_flash_led_remove(struct platform_device *pdev)
{
struct qcom_flash_data *flash_data = platform_get_drvdata(pdev);
......@@ -763,7 +763,6 @@ static int qcom_flash_led_remove(struct platform_device *pdev)
v4l2_flash_release(flash_data->v4l2_flash[flash_data->leds_count--]);
mutex_destroy(&flash_data->lock);
return 0;
}
static const struct of_device_id qcom_flash_led_match_table[] = {
......@@ -778,7 +777,7 @@ static struct platform_driver qcom_flash_led_driver = {
.of_match_table = qcom_flash_led_match_table,
},
.probe = qcom_flash_led_probe,
.remove = qcom_flash_led_remove,
.remove_new = qcom_flash_led_remove,
};
module_platform_driver(qcom_flash_led_driver);
......
......@@ -367,15 +367,13 @@ static int rt8515_probe(struct platform_device *pdev)
return 0;
}
static int rt8515_remove(struct platform_device *pdev)
static void rt8515_remove(struct platform_device *pdev)
{
struct rt8515 *rt = platform_get_drvdata(pdev);
rt8515_v4l2_flash_release(rt);
del_timer_sync(&rt->powerdown_timer);
mutex_destroy(&rt->lock);
return 0;
}
static const struct of_device_id rt8515_match[] = {
......@@ -390,7 +388,7 @@ static struct platform_driver rt8515_driver = {
.of_match_table = rt8515_match,
},
.probe = rt8515_probe,
.remove = rt8515_remove,
.remove_new = rt8515_remove,
};
module_platform_driver(rt8515_driver);
......
......@@ -278,15 +278,13 @@ static int sgm3140_probe(struct platform_device *pdev)
return ret;
}
static int sgm3140_remove(struct platform_device *pdev)
static void sgm3140_remove(struct platform_device *pdev)
{
struct sgm3140 *priv = platform_get_drvdata(pdev);
del_timer_sync(&priv->powerdown_timer);
v4l2_flash_release(priv->v4l2_flash);
return 0;
}
static const struct of_device_id sgm3140_dt_match[] = {
......@@ -299,7 +297,7 @@ MODULE_DEVICE_TABLE(of, sgm3140_dt_match);
static struct platform_driver sgm3140_driver = {
.probe = sgm3140_probe,
.remove = sgm3140_remove,
.remove_new = sgm3140_remove,
.driver = {
.name = "sgm3140",
.of_match_table = sgm3140_dt_match,
......
......@@ -36,6 +36,11 @@ const char * const led_colors[LED_COLOR_ID_MAX] = {
[LED_COLOR_ID_IR] = "ir",
[LED_COLOR_ID_MULTI] = "multicolor",
[LED_COLOR_ID_RGB] = "rgb",
[LED_COLOR_ID_PURPLE] = "purple",
[LED_COLOR_ID_ORANGE] = "orange",
[LED_COLOR_ID_PINK] = "pink",
[LED_COLOR_ID_CYAN] = "cyan",
[LED_COLOR_ID_LIME] = "lime",
};
EXPORT_SYMBOL_GPL(led_colors);
......@@ -359,17 +364,17 @@ EXPORT_SYMBOL_GPL(led_set_brightness_sync);
int led_update_brightness(struct led_classdev *led_cdev)
{
int ret = 0;
int ret;
if (led_cdev->brightness_get) {
ret = led_cdev->brightness_get(led_cdev);
if (ret >= 0) {
led_cdev->brightness = ret;
return 0;
}
if (ret < 0)
return ret;
led_cdev->brightness = ret;
}
return ret;
return 0;
}
EXPORT_SYMBOL_GPL(led_update_brightness);
......
......@@ -215,13 +215,11 @@ static int pm860x_led_probe(struct platform_device *pdev)
return 0;
}
static int pm860x_led_remove(struct platform_device *pdev)
static void pm860x_led_remove(struct platform_device *pdev)
{
struct pm860x_led *data = platform_get_drvdata(pdev);
led_classdev_unregister(&data->cdev);
return 0;
}
static struct platform_driver pm860x_led_driver = {
......@@ -229,7 +227,7 @@ static struct platform_driver pm860x_led_driver = {
.name = "88pm860x-led",
},
.probe = pm860x_led_probe,
.remove = pm860x_led_remove,
.remove_new = pm860x_led_remove,
};
module_platform_driver(pm860x_led_driver);
......
......@@ -163,7 +163,7 @@ static int adp5520_led_probe(struct platform_device *pdev)
return ret;
}
static int adp5520_led_remove(struct platform_device *pdev)
static void adp5520_led_remove(struct platform_device *pdev)
{
struct adp5520_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct adp5520_led *led;
......@@ -177,8 +177,6 @@ static int adp5520_led_remove(struct platform_device *pdev)
for (i = 0; i < pdata->num_leds; i++) {
led_classdev_unregister(&led[i].cdev);
}
return 0;
}
static struct platform_driver adp5520_led_driver = {
......@@ -186,7 +184,7 @@ static struct platform_driver adp5520_led_driver = {
.name = "adp5520-led",
},
.probe = adp5520_led_probe,
.remove = adp5520_led_remove,
.remove_new = adp5520_led_remove,
};
module_platform_driver(adp5520_led_driver);
......
......@@ -112,7 +112,7 @@ struct aw200xx {
struct mutex mutex;
u32 num_leds;
u32 display_rows;
struct aw200xx_led leds[];
struct aw200xx_led leds[] __counted_by(num_leds);
};
static ssize_t dim_show(struct device *dev, struct device_attribute *devattr,
......@@ -479,7 +479,7 @@ static const struct regmap_config aw200xx_regmap_config = {
.num_ranges = ARRAY_SIZE(aw200xx_ranges),
.rd_table = &aw200xx_readable_table,
.wr_table = &aw200xx_writeable_table,
.cache_type = REGCACHE_RBTREE,
.cache_type = REGCACHE_MAPLE,
};
static int aw200xx_probe(struct i2c_client *client)
......
......@@ -159,14 +159,13 @@ static int __init clevo_mail_led_probe(struct platform_device *pdev)
return led_classdev_register(&pdev->dev, &clevo_mail_led);
}
static int clevo_mail_led_remove(struct platform_device *pdev)
static void clevo_mail_led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&clevo_mail_led);
return 0;
}
static struct platform_driver clevo_mail_led_driver = {
.remove = clevo_mail_led_remove,
.remove_new = clevo_mail_led_remove,
.driver = {
.name = KBUILD_MODNAME,
},
......
......@@ -56,7 +56,7 @@ struct cr0014114 {
struct spi_device *spi;
u8 *buf;
unsigned long delay;
struct cr0014114_led leds[];
struct cr0014114_led leds[] __counted_by(count);
};
static void cr0014114_calc_crc(u8 *buf, const size_t len)
......
......@@ -121,13 +121,11 @@ static int da903x_led_probe(struct platform_device *pdev)
return 0;
}
static int da903x_led_remove(struct platform_device *pdev)
static void da903x_led_remove(struct platform_device *pdev)
{
struct da903x_led *led = platform_get_drvdata(pdev);
led_classdev_unregister(&led->cdev);
return 0;
}
static struct platform_driver da903x_led_driver = {
......@@ -135,7 +133,7 @@ static struct platform_driver da903x_led_driver = {
.name = "da903x-led",
},
.probe = da903x_led_probe,
.remove = da903x_led_remove,
.remove_new = da903x_led_remove,
};
module_platform_driver(da903x_led_driver);
......
......@@ -156,7 +156,7 @@ static int da9052_led_probe(struct platform_device *pdev)
return error;
}
static int da9052_led_remove(struct platform_device *pdev)
static void da9052_led_remove(struct platform_device *pdev)
{
struct da9052_led *led = platform_get_drvdata(pdev);
struct da9052_pdata *pdata;
......@@ -172,8 +172,6 @@ static int da9052_led_remove(struct platform_device *pdev)
da9052_set_led_brightness(&led[i], LED_OFF);
led_classdev_unregister(&led[i].cdev);
}
return 0;
}
static struct platform_driver da9052_led_driver = {
......@@ -181,7 +179,7 @@ static struct platform_driver da9052_led_driver = {
.name = "da9052-leds",
},
.probe = da9052_led_probe,
.remove = da9052_led_remove,
.remove_new = da9052_led_remove,
};
module_platform_driver(da9052_led_driver);
......
......@@ -80,7 +80,7 @@ struct el15203000 {
struct spi_device *spi;
unsigned long delay;
size_t count;
struct el15203000_led leds[];
struct el15203000_led leds[] __counted_by(count);
};
#define to_el15203000_led(d) container_of(d, struct el15203000_led, ldev)
......
......@@ -6,17 +6,21 @@
* Raphael Assenat <raph@8d.com>
* Copyright (C) 2008 Freescale Semiconductor, Inc.
*/
#include <linux/container_of.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/overflow.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/types.h>
#include "leds.h"
struct gpio_led_data {
......@@ -125,16 +129,13 @@ static int create_gpio_led(const struct gpio_led *template,
return ret;
pinctrl = devm_pinctrl_get_select_default(led_dat->cdev.dev);
if (IS_ERR(pinctrl)) {
ret = PTR_ERR(pinctrl);
if (ret != -ENODEV) {
dev_warn(led_dat->cdev.dev,
"Failed to select %pOF pinctrl: %d\n",
to_of_node(fwnode), ret);
} else {
/* pinctrl-%d not present, not an error */
ret = 0;
}
ret = PTR_ERR_OR_ZERO(pinctrl);
/* pinctrl-%d not present, not an error */
if (ret == -ENODEV)
ret = 0;
if (ret) {
dev_warn(led_dat->cdev.dev, "Failed to select %pfw pinctrl: %d\n",
fwnode, ret);
}
return ret;
......@@ -142,12 +143,11 @@ static int create_gpio_led(const struct gpio_led *template,
struct gpio_leds_priv {
int num_leds;
struct gpio_led_data leds[];
struct gpio_led_data leds[] __counted_by(num_leds);
};
static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
static struct gpio_leds_priv *gpio_leds_create(struct device *dev)
{
struct device *dev = &pdev->dev;
struct fwnode_handle *child;
struct gpio_leds_priv *priv;
int count, ret;
......@@ -221,13 +221,13 @@ static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx,
* device, this will hit the board file, if any and get
* the GPIO from there.
*/
gpiod = devm_gpiod_get_index(dev, NULL, idx, GPIOD_OUT_LOW);
if (!IS_ERR(gpiod)) {
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;
}
if (PTR_ERR(gpiod) != -ENOENT)
return gpiod;
/*
* This is the legacy code path for platform code that
......@@ -256,13 +256,13 @@ static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx,
static int gpio_led_probe(struct platform_device *pdev)
{
struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct device *dev = &pdev->dev;
struct gpio_led_platform_data *pdata = dev_get_platdata(dev);
struct gpio_leds_priv *priv;
int i, ret = 0;
int i, ret;
if (pdata && pdata->num_leds) {
priv = devm_kzalloc(&pdev->dev, struct_size(priv, leds, pdata->num_leds),
GFP_KERNEL);
priv = devm_kzalloc(dev, struct_size(priv, leds, pdata->num_leds), GFP_KERNEL);
if (!priv)
return -ENOMEM;
......@@ -275,22 +275,20 @@ static int gpio_led_probe(struct platform_device *pdev)
led_dat->gpiod = template->gpiod;
else
led_dat->gpiod =
gpio_led_get_gpiod(&pdev->dev,
i, template);
gpio_led_get_gpiod(dev, i, template);
if (IS_ERR(led_dat->gpiod)) {
dev_info(&pdev->dev, "Skipping unavailable LED gpio %d (%s)\n",
dev_info(dev, "Skipping unavailable LED gpio %d (%s)\n",
template->gpio, template->name);
continue;
}
ret = create_gpio_led(template, led_dat,
&pdev->dev, NULL,
ret = create_gpio_led(template, led_dat, dev, NULL,
pdata->gpio_blink_set);
if (ret < 0)
return ret;
}
} else {
priv = gpio_leds_create(pdev);
priv = gpio_leds_create(dev);
if (IS_ERR(priv))
return PTR_ERR(priv);
}
......
......@@ -718,7 +718,7 @@ static int lm3533_led_probe(struct platform_device *pdev)
return ret;
}
static int lm3533_led_remove(struct platform_device *pdev)
static void lm3533_led_remove(struct platform_device *pdev)
{
struct lm3533_led *led = platform_get_drvdata(pdev);
......@@ -726,8 +726,6 @@ static int lm3533_led_remove(struct platform_device *pdev)
lm3533_ctrlbank_disable(&led->cb);
led_classdev_unregister(&led->cdev);
return 0;
}
static void lm3533_led_shutdown(struct platform_device *pdev)
......@@ -746,7 +744,7 @@ static struct platform_driver lm3533_led_driver = {
.name = "lm3533-leds",
},
.probe = lm3533_led_probe,
.remove = lm3533_led_remove,
.remove_new = lm3533_led_remove,
.shutdown = lm3533_led_shutdown,
};
module_platform_driver(lm3533_led_driver);
......
......@@ -139,7 +139,7 @@ static const struct regmap_config lm3692x_regmap_config = {
.max_register = LM3692X_FAULT_FLAGS,
.reg_defaults = lm3692x_reg_defs,
.num_reg_defaults = ARRAY_SIZE(lm3692x_reg_defs),
.cache_type = REGCACHE_RBTREE,
.cache_type = REGCACHE_MAPLE,
};
static int lm3692x_fault_check(struct lm3692x_led *led)
......
......@@ -89,7 +89,7 @@ struct lm3697 {
int bank_cfg;
int num_banks;
struct lm3697_led leds[];
struct lm3697_led leds[] __counted_by(num_banks);
};
static const struct reg_default lm3697_reg_defs[] = {
......
......@@ -101,7 +101,7 @@ static int lp3952_get_label(struct device *dev, const char *label, char *dest)
if (ret)
return ret;
strncpy(dest, str, LP3952_LABEL_MAX_LEN);
strscpy(dest, str, LP3952_LABEL_MAX_LEN);
return 0;
}
......@@ -204,7 +204,7 @@ static const struct regmap_config lp3952_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = REG_MAX,
.cache_type = REGCACHE_RBTREE,
.cache_type = REGCACHE_MAPLE,
};
static int lp3952_probe(struct i2c_client *client)
......
......@@ -301,6 +301,8 @@ static int lp5521_post_init_device(struct lp55xx_chip *chip)
/* Set all PWMs to direct control mode */
ret = lp55xx_write(chip, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT);
if (ret)
return ret;
/* Update configuration for the clock setting */
val = LP5521_DEFAULT_CFG;
......
......@@ -442,9 +442,9 @@ int lp55xx_init_device(struct lp55xx_chip *chip)
gpiod_direction_output(pdata->enable_gpiod, 0);
gpiod_set_consumer_name(pdata->enable_gpiod, "LP55xx enable");
gpiod_set_value(pdata->enable_gpiod, 0);
gpiod_set_value_cansleep(pdata->enable_gpiod, 0);
usleep_range(1000, 2000); /* Keep enable down at least 1ms */
gpiod_set_value(pdata->enable_gpiod, 1);
gpiod_set_value_cansleep(pdata->enable_gpiod, 1);
usleep_range(1000, 2000); /* 500us abs min. */
}
......
......@@ -261,15 +261,13 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
return ret;
}
static int mc13xxx_led_remove(struct platform_device *pdev)
static void mc13xxx_led_remove(struct platform_device *pdev)
{
struct mc13xxx_leds *leds = platform_get_drvdata(pdev);
int i;
for (i = 0; i < leds->num_leds; i++)
led_classdev_unregister(&leds->led[i].cdev);
return 0;
}
static const struct mc13xxx_led_devtype mc13783_led_devtype = {
......@@ -305,7 +303,7 @@ static struct platform_driver mc13xxx_led_driver = {
.driver = {
.name = "mc13xxx-led",
},
.remove = mc13xxx_led_remove,
.remove_new = mc13xxx_led_remove,
.id_table = mc13xxx_led_id_table,
};
module_platform_driver_probe(mc13xxx_led_driver, mc13xxx_led_probe);
......
......@@ -275,13 +275,11 @@ static int mlxreg_led_probe(struct platform_device *pdev)
return mlxreg_led_config(priv);
}
static int mlxreg_led_remove(struct platform_device *pdev)
static void mlxreg_led_remove(struct platform_device *pdev)
{
struct mlxreg_led_priv_data *priv = dev_get_drvdata(&pdev->dev);
mutex_destroy(&priv->access_lock);
return 0;
}
static struct platform_driver mlxreg_led_driver = {
......@@ -289,7 +287,7 @@ static struct platform_driver mlxreg_led_driver = {
.name = "leds-mlxreg",
},
.probe = mlxreg_led_probe,
.remove = mlxreg_led_remove,
.remove_new = mlxreg_led_remove,
};
module_platform_driver(mlxreg_led_driver);
......
......@@ -632,7 +632,7 @@ static int mt6323_led_probe(struct platform_device *pdev)
return ret;
}
static int mt6323_led_remove(struct platform_device *pdev)
static void mt6323_led_remove(struct platform_device *pdev)
{
struct mt6323_leds *leds = platform_get_drvdata(pdev);
const struct mt6323_regs *regs = leds->pdata->regs;
......@@ -647,8 +647,6 @@ static int mt6323_led_remove(struct platform_device *pdev)
RG_DRV_32K_CK_PDN);
mutex_destroy(&leds->lock);
return 0;
}
static const struct mt6323_regs mt6323_registers = {
......@@ -723,7 +721,7 @@ MODULE_DEVICE_TABLE(of, mt6323_led_dt_match);
static struct platform_driver mt6323_led_driver = {
.probe = mt6323_led_probe,
.remove = mt6323_led_remove,
.remove_new = mt6323_led_remove,
.driver = {
.name = "mt6323-led",
.of_match_table = mt6323_led_dt_match,
......
......@@ -167,15 +167,13 @@ static int nic78bx_probe(struct platform_device *pdev)
return ret;
}
static int nic78bx_remove(struct platform_device *pdev)
static void nic78bx_remove(struct platform_device *pdev)
{
struct nic78bx_led_data *led_data = platform_get_drvdata(pdev);
/* Lock LED register */
outb(NIC78BX_LOCK_VALUE,
led_data->io_base + NIC78BX_LOCK_REG_OFFSET);
return 0;
}
static const struct acpi_device_id led_device_ids[] = {
......@@ -186,7 +184,7 @@ MODULE_DEVICE_TABLE(acpi, led_device_ids);
static struct platform_driver led_driver = {
.probe = nic78bx_probe,
.remove = nic78bx_remove,
.remove_new = nic78bx_remove,
.driver = {
.name = KBUILD_MODNAME,
.acpi_match_table = ACPI_PTR(led_device_ids),
......
......@@ -76,7 +76,7 @@ struct pca955x_chipdef {
int slv_addr_shift; /* Number of bits to ignore */
};
static struct pca955x_chipdef pca955x_chipdefs[] = {
static const struct pca955x_chipdef pca955x_chipdefs[] = {
[pca9550] = {
.bits = 2,
.slv_addr = /* 110000x */ 0x60,
......@@ -104,20 +104,10 @@ static struct pca955x_chipdef pca955x_chipdefs[] = {
},
};
static const struct i2c_device_id pca955x_id[] = {
{ "pca9550", pca9550 },
{ "pca9551", pca9551 },
{ "pca9552", pca9552 },
{ "ibm-pca9552", ibm_pca9552 },
{ "pca9553", pca9553 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pca955x_id);
struct pca955x {
struct mutex lock;
struct pca955x_led *leds;
struct pca955x_chipdef *chipdef;
const struct pca955x_chipdef *chipdef;
struct i2c_client *client;
unsigned long active_pins;
#ifdef CONFIG_LEDS_PCA955X_GPIO
......@@ -415,7 +405,7 @@ static int pca955x_gpio_direction_output(struct gpio_chip *gc,
#endif /* CONFIG_LEDS_PCA955X_GPIO */
static struct pca955x_platform_data *
pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip)
pca955x_get_pdata(struct i2c_client *client, const struct pca955x_chipdef *chip)
{
struct pca955x_platform_data *pdata;
struct pca955x_led *led;
......@@ -457,21 +447,11 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip)
return pdata;
}
static const struct of_device_id of_pca955x_match[] = {
{ .compatible = "nxp,pca9550", .data = (void *)pca9550 },
{ .compatible = "nxp,pca9551", .data = (void *)pca9551 },
{ .compatible = "nxp,pca9552", .data = (void *)pca9552 },
{ .compatible = "ibm,pca9552", .data = (void *)ibm_pca9552 },
{ .compatible = "nxp,pca9553", .data = (void *)pca9553 },
{},
};
MODULE_DEVICE_TABLE(of, of_pca955x_match);
static int pca955x_probe(struct i2c_client *client)
{
struct pca955x *pca955x;
struct pca955x_led *pca955x_led;
struct pca955x_chipdef *chip;
const struct pca955x_chipdef *chip;
struct led_classdev *led;
struct led_init_data init_data;
struct i2c_adapter *adapter;
......@@ -480,24 +460,11 @@ static int pca955x_probe(struct i2c_client *client)
bool set_default_label = false;
bool keep_pwm = false;
char default_label[8];
enum pca955x_type chip_type;
const void *md = device_get_match_data(&client->dev);
if (md) {
chip_type = (enum pca955x_type)md;
} else {
const struct i2c_device_id *id = i2c_match_id(pca955x_id,
client);
if (id) {
chip_type = (enum pca955x_type)id->driver_data;
} else {
dev_err(&client->dev, "unknown chip\n");
return -ENODEV;
}
}
chip = &pca955x_chipdefs[chip_type];
chip = i2c_get_match_data(client);
if (!chip)
return dev_err_probe(&client->dev, -ENODEV, "unknown chip\n");
adapter = client->adapter;
pdata = dev_get_platdata(&client->dev);
if (!pdata) {
......@@ -663,6 +630,26 @@ static int pca955x_probe(struct i2c_client *client)
return 0;
}
static const struct i2c_device_id pca955x_id[] = {
{ "pca9550", (kernel_ulong_t)&pca955x_chipdefs[pca9550] },
{ "pca9551", (kernel_ulong_t)&pca955x_chipdefs[pca9551] },
{ "pca9552", (kernel_ulong_t)&pca955x_chipdefs[pca9552] },
{ "ibm-pca9552", (kernel_ulong_t)&pca955x_chipdefs[ibm_pca9552] },
{ "pca9553", (kernel_ulong_t)&pca955x_chipdefs[pca9553] },
{}
};
MODULE_DEVICE_TABLE(i2c, pca955x_id);
static const struct of_device_id of_pca955x_match[] = {
{ .compatible = "nxp,pca9550", .data = &pca955x_chipdefs[pca9550] },
{ .compatible = "nxp,pca9551", .data = &pca955x_chipdefs[pca9551] },
{ .compatible = "nxp,pca9552", .data = &pca955x_chipdefs[pca9552] },
{ .compatible = "ibm,pca9552", .data = &pca955x_chipdefs[ibm_pca9552] },
{ .compatible = "nxp,pca9553", .data = &pca955x_chipdefs[pca9553] },
{}
};
MODULE_DEVICE_TABLE(of, of_pca955x_match);
static struct i2c_driver pca955x_driver = {
.driver = {
.name = "leds-pca955x",
......
......@@ -309,7 +309,7 @@ static int powernv_led_probe(struct platform_device *pdev)
}
/* Platform driver remove */
static int powernv_led_remove(struct platform_device *pdev)
static void powernv_led_remove(struct platform_device *pdev)
{
struct powernv_led_common *powernv_led_common;
......@@ -321,7 +321,6 @@ static int powernv_led_remove(struct platform_device *pdev)
mutex_destroy(&powernv_led_common->lock);
dev_info(&pdev->dev, "PowerNV led module unregistered\n");
return 0;
}
/* Platform driver property match */
......@@ -335,7 +334,7 @@ MODULE_DEVICE_TABLE(of, powernv_led_match);
static struct platform_driver powernv_led_driver = {
.probe = powernv_led_probe,
.remove = powernv_led_remove,
.remove_new = powernv_led_remove,
.driver = {
.name = "powernv-led-driver",
.of_match_table = powernv_led_match,
......
......@@ -53,7 +53,7 @@ static int led_pwm_set(struct led_classdev *led_cdev,
duty = led_dat->pwmstate.period - duty;
led_dat->pwmstate.duty_cycle = duty;
led_dat->pwmstate.enabled = duty > 0;
led_dat->pwmstate.enabled = true;
return pwm_apply_state(led_dat->pwm, &led_dat->pwmstate);
}
......
......@@ -42,15 +42,14 @@ static int rb532_led_probe(struct platform_device *pdev)
return led_classdev_register(&pdev->dev, &rb532_uled);
}
static int rb532_led_remove(struct platform_device *pdev)
static void rb532_led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&rb532_uled);
return 0;
}
static struct platform_driver rb532_led_driver = {
.probe = rb532_led_probe,
.remove = rb532_led_remove,
.remove_new = rb532_led_remove,
.driver = {
.name = "rb532-led",
},
......
......@@ -173,13 +173,12 @@ static int regulator_led_probe(struct platform_device *pdev)
return 0;
}
static int regulator_led_remove(struct platform_device *pdev)
static void regulator_led_remove(struct platform_device *pdev)
{
struct regulator_led *led = platform_get_drvdata(pdev);
led_classdev_unregister(&led->cdev);
regulator_led_disable(led);
return 0;
}
static const struct of_device_id regulator_led_of_match[] = {
......@@ -194,7 +193,7 @@ static struct platform_driver regulator_led_driver = {
.of_match_table = regulator_led_of_match,
},
.probe = regulator_led_probe,
.remove = regulator_led_remove,
.remove_new = regulator_led_remove,
};
module_platform_driver(regulator_led_driver);
......
......@@ -296,7 +296,6 @@ static int sc27xx_led_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, priv);
mutex_init(&priv->lock);
priv->base = base;
priv->regmap = dev_get_regmap(dev->parent, NULL);
if (!priv->regmap) {
......@@ -309,13 +308,11 @@ static int sc27xx_led_probe(struct platform_device *pdev)
err = of_property_read_u32(child, "reg", &reg);
if (err) {
of_node_put(child);
mutex_destroy(&priv->lock);
return err;
}
if (reg >= SC27XX_LEDS_MAX || priv->leds[reg].active) {
of_node_put(child);
mutex_destroy(&priv->lock);
return -EINVAL;
}
......@@ -323,6 +320,8 @@ static int sc27xx_led_probe(struct platform_device *pdev)
priv->leds[reg].active = true;
}
mutex_init(&priv->lock);
err = sc27xx_led_register(dev, priv);
if (err)
mutex_destroy(&priv->lock);
......@@ -330,12 +329,11 @@ static int sc27xx_led_probe(struct platform_device *pdev)
return err;
}
static int sc27xx_led_remove(struct platform_device *pdev)
static void sc27xx_led_remove(struct platform_device *pdev)
{
struct sc27xx_led_priv *priv = platform_get_drvdata(pdev);
mutex_destroy(&priv->lock);
return 0;
}
static const struct of_device_id sc27xx_led_of_match[] = {
......@@ -350,7 +348,7 @@ static struct platform_driver sc27xx_led_driver = {
.of_match_table = sc27xx_led_of_match,
},
.probe = sc27xx_led_probe,
.remove = sc27xx_led_remove,
.remove_new = sc27xx_led_remove,
};
module_platform_driver(sc27xx_led_driver);
......
......@@ -163,15 +163,13 @@ static int sunfire_led_generic_probe(struct platform_device *pdev,
return 0;
}
static int sunfire_led_generic_remove(struct platform_device *pdev)
static void sunfire_led_generic_remove(struct platform_device *pdev)
{
struct sunfire_drvdata *p = platform_get_drvdata(pdev);
int i;
for (i = 0; i < NUM_LEDS_PER_BOARD; i++)
led_classdev_unregister(&p->leds[i].led_cdev);
return 0;
}
static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = {
......@@ -221,7 +219,7 @@ MODULE_ALIAS("platform:sunfire-fhc-leds");
static struct platform_driver sunfire_clockboard_led_driver = {
.probe = sunfire_clockboard_led_probe,
.remove = sunfire_led_generic_remove,
.remove_new = sunfire_led_generic_remove,
.driver = {
.name = "sunfire-clockboard-leds",
},
......@@ -229,7 +227,7 @@ static struct platform_driver sunfire_clockboard_led_driver = {
static struct platform_driver sunfire_fhc_led_driver = {
.probe = sunfire_fhc_led_probe,
.remove = sunfire_led_generic_remove,
.remove_new = sunfire_led_generic_remove,
.driver = {
.name = "sunfire-fhc-leds",
},
......
......@@ -92,9 +92,6 @@
struct tca6507_platform_data {
struct led_platform_data leds;
#ifdef CONFIG_GPIOLIB
int gpio_base;
#endif
};
#define TCA6507_MAKE_GPIO 1
......@@ -636,7 +633,7 @@ static int tca6507_probe_gpios(struct device *dev,
tca->gpio.label = "gpio-tca6507";
tca->gpio.ngpio = gpios;
tca->gpio.base = pdata->gpio_base;
tca->gpio.base = -1;
tca->gpio.owner = THIS_MODULE;
tca->gpio.direction_output = tca6507_gpio_direction_output;
tca->gpio.set = tca6507_gpio_set_value;
......@@ -715,9 +712,6 @@ tca6507_led_dt_init(struct device *dev)
pdata->leds.leds = tca_leds;
pdata->leds.num_leds = NUM_LEDS;
#ifdef CONFIG_GPIOLIB
pdata->gpio_base = -1;
#endif
return pdata;
}
......
This diff is collapsed.
......@@ -280,13 +280,11 @@ static int wm831x_status_probe(struct platform_device *pdev)
return 0;
}
static int wm831x_status_remove(struct platform_device *pdev)
static void wm831x_status_remove(struct platform_device *pdev)
{
struct wm831x_status *drvdata = platform_get_drvdata(pdev);
led_classdev_unregister(&drvdata->cdev);
return 0;
}
static struct platform_driver wm831x_status_driver = {
......@@ -294,7 +292,7 @@ static struct platform_driver wm831x_status_driver = {
.name = "wm831x-status",
},
.probe = wm831x_status_probe,
.remove = wm831x_status_remove,
.remove_new = wm831x_status_remove,
};
module_platform_driver(wm831x_status_driver);
......
......@@ -242,13 +242,12 @@ static int wm8350_led_probe(struct platform_device *pdev)
return led_classdev_register(&pdev->dev, &led->cdev);
}
static int wm8350_led_remove(struct platform_device *pdev)
static void wm8350_led_remove(struct platform_device *pdev)
{
struct wm8350_led *led = platform_get_drvdata(pdev);
led_classdev_unregister(&led->cdev);
wm8350_led_disable(led);
return 0;
}
static struct platform_driver wm8350_led_driver = {
......@@ -256,7 +255,7 @@ static struct platform_driver wm8350_led_driver = {
.name = "wm8350-led",
},
.probe = wm8350_led_probe,
.remove = wm8350_led_remove,
.remove_new = wm8350_led_remove,
.shutdown = wm8350_led_shutdown,
};
......
......@@ -14,6 +14,19 @@ config LEDS_GROUP_MULTICOLOR
To compile this driver as a module, choose M here: the module
will be called leds-group-multicolor.
config LEDS_KTD202X
tristate "LED support for KTD202x Chips"
depends on I2C
depends on OF
select REGMAP_I2C
help
This option enables support for the Kinetic KTD2026/KTD2027
RGB/White LED driver found in different BQ mobile phones.
It is a 3 or 4 channel LED driver programmed via an I2C interface.
To compile this driver as a module, choose M here: the module
will be called leds-ktd202x.
config LEDS_PWM_MULTICOLOR
tristate "PWM driven multi-color LED Support"
depends on PWM
......
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_LEDS_GROUP_MULTICOLOR) += leds-group-multicolor.o
obj-$(CONFIG_LEDS_KTD202X) += leds-ktd202x.o
obj-$(CONFIG_LEDS_PWM_MULTICOLOR) += leds-pwm-multicolor.o
obj-$(CONFIG_LEDS_QCOM_LPG) += leds-qcom-lpg.o
obj-$(CONFIG_LEDS_MT6370_RGB) += leds-mt6370-rgb.o
This diff is collapsed.
......@@ -153,7 +153,7 @@ struct mt6370_priv {
const struct mt6370_pdata *pdata;
unsigned int leds_count;
unsigned int leds_active;
struct mt6370_led leds[];
struct mt6370_led leds[] __counted_by(leds_count);
};
static const struct reg_field common_reg_fields[F_MAX_FIELDS] = {
......
......@@ -173,7 +173,7 @@ struct lpg_led {
struct led_classdev_mc mcdev;
unsigned int num_channels;
struct lpg_channel *channels[];
struct lpg_channel *channels[] __counted_by(num_channels);
};
/**
......@@ -1364,13 +1364,11 @@ static int lpg_probe(struct platform_device *pdev)
return lpg_add_pwm(lpg);
}
static int lpg_remove(struct platform_device *pdev)
static void lpg_remove(struct platform_device *pdev)
{
struct lpg *lpg = platform_get_drvdata(pdev);
pwmchip_remove(&lpg->pwm);
return 0;
}
static const struct lpg_data pm8916_pwm_data = {
......@@ -1532,7 +1530,7 @@ MODULE_DEVICE_TABLE(of, lpg_of_table);
static struct platform_driver lpg_driver = {
.probe = lpg_probe,
.remove = lpg_remove,
.remove_new = lpg_remove,
.driver = {
.name = "qcom-spmi-lpg",
.of_match_table = lpg_of_table,
......
......@@ -45,15 +45,15 @@ static int simatic_ipc_leds_gpio_apollolake_probe(struct platform_device *pdev)
&simatic_ipc_led_gpio_table_extra);
}
static int simatic_ipc_leds_gpio_apollolake_remove(struct platform_device *pdev)
static void simatic_ipc_leds_gpio_apollolake_remove(struct platform_device *pdev)
{
return simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table,
&simatic_ipc_led_gpio_table_extra);
simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table,
&simatic_ipc_led_gpio_table_extra);
}
static struct platform_driver simatic_ipc_led_gpio_apollolake_driver = {
.probe = simatic_ipc_leds_gpio_apollolake_probe,
.remove = simatic_ipc_leds_gpio_apollolake_remove,
.remove_new = simatic_ipc_leds_gpio_apollolake_remove,
.driver = {
.name = KBUILD_MODNAME,
},
......
......@@ -33,15 +33,13 @@ static const struct gpio_led_platform_data simatic_ipc_gpio_leds_pdata = {
.leds = simatic_ipc_gpio_leds,
};
int simatic_ipc_leds_gpio_remove(struct platform_device *pdev,
void simatic_ipc_leds_gpio_remove(struct platform_device *pdev,
struct gpiod_lookup_table *table,
struct gpiod_lookup_table *table_extra)
{
gpiod_remove_lookup_table(table);
gpiod_remove_lookup_table(table_extra);
platform_device_unregister(simatic_leds_pdev);
return 0;
}
EXPORT_SYMBOL_GPL(simatic_ipc_leds_gpio_remove);
......
......@@ -36,15 +36,14 @@ static int simatic_ipc_leds_gpio_elkhartlake_probe(struct platform_device *pdev)
NULL);
}
static int simatic_ipc_leds_gpio_elkhartlake_remove(struct platform_device *pdev)
static void simatic_ipc_leds_gpio_elkhartlake_remove(struct platform_device *pdev)
{
return simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table,
NULL);
simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table, NULL);
}
static struct platform_driver simatic_ipc_led_gpio_elkhartlake_driver = {
.probe = simatic_ipc_leds_gpio_elkhartlake_probe,
.remove = simatic_ipc_leds_gpio_elkhartlake_remove,
.remove_new = simatic_ipc_leds_gpio_elkhartlake_remove,
.driver = {
.name = KBUILD_MODNAME,
},
......
......@@ -45,15 +45,15 @@ static int simatic_ipc_leds_gpio_f7188x_probe(struct platform_device *pdev)
&simatic_ipc_led_gpio_table_extra);
}
static int simatic_ipc_leds_gpio_f7188x_remove(struct platform_device *pdev)
static void simatic_ipc_leds_gpio_f7188x_remove(struct platform_device *pdev)
{
return simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table,
&simatic_ipc_led_gpio_table_extra);
simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table,
&simatic_ipc_led_gpio_table_extra);
}
static struct platform_driver simatic_ipc_led_gpio_driver = {
.probe = simatic_ipc_leds_gpio_f7188x_probe,
.remove = simatic_ipc_leds_gpio_f7188x_remove,
.remove_new = simatic_ipc_leds_gpio_f7188x_remove,
.driver = {
.name = KBUILD_MODNAME,
},
......
......@@ -15,8 +15,8 @@ int simatic_ipc_leds_gpio_probe(struct platform_device *pdev,
struct gpiod_lookup_table *table,
struct gpiod_lookup_table *table_extra);
int simatic_ipc_leds_gpio_remove(struct platform_device *pdev,
struct gpiod_lookup_table *table,
struct gpiod_lookup_table *table_extra);
void simatic_ipc_leds_gpio_remove(struct platform_device *pdev,
struct gpiod_lookup_table *table,
struct gpiod_lookup_table *table_extra);
#endif /* _SIMATIC_IPC_LEDS_GPIO_H */
......@@ -83,13 +83,10 @@ config LEDS_TRIGGER_ACTIVITY
config LEDS_TRIGGER_GPIO
tristate "LED GPIO Trigger"
depends on GPIOLIB || COMPILE_TEST
depends on BROKEN
help
This allows LEDs to be controlled by gpio events. It's good
when using gpios as switches and triggering the needed LEDs
from there. One use case is n810's keypad LEDs that could
be triggered by this trigger when user slides up to show
keypad.
from there. Triggers are defined as device properties.
If unsure, say N.
......
......@@ -130,7 +130,7 @@ static int ledtrig_prepare_down_cpu(unsigned int cpu)
static int __init ledtrig_cpu_init(void)
{
int cpu;
unsigned int cpu;
int ret;
/* Supports up to 9999 cpu cores */
......@@ -152,7 +152,7 @@ static int __init ledtrig_cpu_init(void)
if (cpu >= 8)
continue;
snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
snprintf(trig->name, MAX_NAME_LEN, "cpu%u", cpu);
led_trigger_register_simple(trig->name, &trig->_trig);
}
......
......@@ -3,12 +3,13 @@
* ledtrig-gio.c - LED Trigger Based on GPIO events
*
* Copyright 2009 Felipe Balbi <me@felipebalbi.com>
* Copyright 2023 Linus Walleij <linus.walleij@linaro.org>
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/leds.h>
#include <linux/slab.h>
......@@ -16,10 +17,8 @@
struct gpio_trig_data {
struct led_classdev *led;
unsigned desired_brightness; /* desired brightness when led is on */
unsigned inverted; /* true when gpio is inverted */
unsigned gpio; /* gpio that triggers the leds */
struct gpio_desc *gpiod; /* gpio that triggers the led */
};
static irqreturn_t gpio_trig_irq(int irq, void *_led)
......@@ -28,10 +27,7 @@ static irqreturn_t gpio_trig_irq(int irq, void *_led)
struct gpio_trig_data *gpio_data = led_get_trigger_data(led);
int tmp;
tmp = gpio_get_value_cansleep(gpio_data->gpio);
if (gpio_data->inverted)
tmp = !tmp;
tmp = gpiod_get_value_cansleep(gpio_data->gpiod);
if (tmp) {
if (gpio_data->desired_brightness)
led_set_brightness_nosleep(gpio_data->led,
......@@ -73,93 +69,8 @@ static ssize_t gpio_trig_brightness_store(struct device *dev,
static DEVICE_ATTR(desired_brightness, 0644, gpio_trig_brightness_show,
gpio_trig_brightness_store);
static ssize_t gpio_trig_inverted_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);
return sprintf(buf, "%u\n", gpio_data->inverted);
}
static ssize_t gpio_trig_inverted_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t n)
{
struct led_classdev *led = led_trigger_get_led(dev);
struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);
unsigned long inverted;
int ret;
ret = kstrtoul(buf, 10, &inverted);
if (ret < 0)
return ret;
if (inverted > 1)
return -EINVAL;
gpio_data->inverted = inverted;
/* After inverting, we need to update the LED. */
if (gpio_is_valid(gpio_data->gpio))
gpio_trig_irq(0, led);
return n;
}
static DEVICE_ATTR(inverted, 0644, gpio_trig_inverted_show,
gpio_trig_inverted_store);
static ssize_t gpio_trig_gpio_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);
return sprintf(buf, "%u\n", gpio_data->gpio);
}
static ssize_t gpio_trig_gpio_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t n)
{
struct led_classdev *led = led_trigger_get_led(dev);
struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);
unsigned gpio;
int ret;
ret = sscanf(buf, "%u", &gpio);
if (ret < 1) {
dev_err(dev, "couldn't read gpio number\n");
return -EINVAL;
}
if (gpio_data->gpio == gpio)
return n;
if (!gpio_is_valid(gpio)) {
if (gpio_is_valid(gpio_data->gpio))
free_irq(gpio_to_irq(gpio_data->gpio), led);
gpio_data->gpio = gpio;
return n;
}
ret = request_threaded_irq(gpio_to_irq(gpio), NULL, gpio_trig_irq,
IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING, "ledtrig-gpio", led);
if (ret) {
dev_err(dev, "request_irq failed with error %d\n", ret);
} else {
if (gpio_is_valid(gpio_data->gpio))
free_irq(gpio_to_irq(gpio_data->gpio), led);
gpio_data->gpio = gpio;
/* After changing the GPIO, we need to update the LED. */
gpio_trig_irq(0, led);
}
return ret ? ret : n;
}
static DEVICE_ATTR(gpio, 0644, gpio_trig_gpio_show, gpio_trig_gpio_store);
static struct attribute *gpio_trig_attrs[] = {
&dev_attr_desired_brightness.attr,
&dev_attr_inverted.attr,
&dev_attr_gpio.attr,
NULL
};
ATTRIBUTE_GROUPS(gpio_trig);
......@@ -167,16 +78,48 @@ ATTRIBUTE_GROUPS(gpio_trig);
static int gpio_trig_activate(struct led_classdev *led)
{
struct gpio_trig_data *gpio_data;
struct device *dev = led->dev;
int ret;
gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL);
if (!gpio_data)
return -ENOMEM;
gpio_data->led = led;
gpio_data->gpio = -ENOENT;
/*
* The generic property "trigger-sources" is followed,
* and we hope that this is a GPIO.
*/
gpio_data->gpiod = fwnode_gpiod_get_index(dev->fwnode,
"trigger-sources",
0, GPIOD_IN,
"led-trigger");
if (IS_ERR(gpio_data->gpiod)) {
ret = PTR_ERR(gpio_data->gpiod);
kfree(gpio_data);
return ret;
}
if (!gpio_data->gpiod) {
dev_err(dev, "no valid GPIO for the trigger\n");
kfree(gpio_data);
return -EINVAL;
}
gpio_data->led = led;
led_set_trigger_data(led, gpio_data);
ret = request_threaded_irq(gpiod_to_irq(gpio_data->gpiod), NULL, gpio_trig_irq,
IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING, "ledtrig-gpio", led);
if (ret) {
dev_err(dev, "request_irq failed with error %d\n", ret);
gpiod_put(gpio_data->gpiod);
kfree(gpio_data);
return ret;
}
/* Finally update the LED to initial status */
gpio_trig_irq(0, led);
return 0;
}
......@@ -184,8 +127,8 @@ static void gpio_trig_deactivate(struct led_classdev *led)
{
struct gpio_trig_data *gpio_data = led_get_trigger_data(led);
if (gpio_is_valid(gpio_data->gpio))
free_irq(gpio_to_irq(gpio_data->gpio), led);
free_irq(gpiod_to_irq(gpio_data->gpiod), led);
gpiod_put(gpio_data->gpiod);
kfree(gpio_data);
}
......
......@@ -221,6 +221,9 @@ static ssize_t device_name_show(struct device *dev,
static int set_device_name(struct led_netdev_data *trigger_data,
const char *name, size_t size)
{
if (size >= IFNAMSIZ)
return -EINVAL;
cancel_delayed_work_sync(&trigger_data->work);
mutex_lock(&trigger_data->lock);
......@@ -263,9 +266,6 @@ static ssize_t device_name_store(struct device *dev,
struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
int ret;
if (size >= IFNAMSIZ)
return -EINVAL;
ret = set_device_name(trigger_data, buf, size);
if (ret < 0)
......
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