From 51251542c9688c399e14d852258a675b331e761b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Jul 2019 10:47:38 +0200 Subject: leds: max77650: add MODULE_ALIAS() Define a MODULE_ALIAS() in the LED sub-driver for max77650 so that the appropriate module gets loaded together with the core mfd driver. Signed-off-by: Bartosz Golaszewski Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max77650.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 8a8e5c65b157..150421387534 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -143,3 +143,4 @@ module_platform_driver(max77650_led_driver); MODULE_DESCRIPTION("MAXIM 77650/77651 LED driver"); MODULE_AUTHOR("Bartosz Golaszewski "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:max77650-led"); -- cgit v1.2.3 From 533016c870a8d0cc01478ed9e780a46e830b3b22 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 4 Jul 2019 16:57:42 -0700 Subject: leds: as3645a: Fix misuse of strlcpy Probable cut&paste typo - use the correct field size. Signed-off-by: Joe Perches Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-as3645a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-as3645a.c b/drivers/leds/leds-as3645a.c index 14ab6b0e4de9..050088dff8dd 100644 --- a/drivers/leds/leds-as3645a.c +++ b/drivers/leds/leds-as3645a.c @@ -668,7 +668,7 @@ static int as3645a_v4l2_setup(struct as3645a *flash) }; strlcpy(cfg.dev_name, led->name, sizeof(cfg.dev_name)); - strlcpy(cfgind.dev_name, flash->iled_cdev.name, sizeof(cfg.dev_name)); + strlcpy(cfgind.dev_name, flash->iled_cdev.name, sizeof(cfgind.dev_name)); flash->vf = v4l2_flash_init( &flash->client->dev, flash->flash_node, &flash->fled, NULL, -- cgit v1.2.3 From 730f693d79da8130c8ac18d1083cdb333fd8d7c8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 11 Jul 2019 13:24:05 +0530 Subject: leds: max77650: Add of_node_put() before return Each iteration of for_each_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence create a new label, err_node_put, which puts the previous node and returns variable rv. Modify the mid-loop return statements to instead store the return value in rv and jump to err_node_put. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Reviewed-by: Dan Murphy Acked-by: Bartosz Golaszewski Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max77650.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 150421387534..04738324b3e6 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -91,8 +91,10 @@ static int max77650_led_probe(struct platform_device *pdev) for_each_child_of_node(of_node, child) { rv = of_property_read_u32(child, "reg", ®); - if (rv || reg >= MAX77650_LED_NUM_LEDS) - return -EINVAL; + if (rv || reg >= MAX77650_LED_NUM_LEDS) { + rv = -EINVAL; + goto err_node_put; + } led = &leds[reg]; led->map = map; @@ -107,8 +109,10 @@ static int max77650_led_probe(struct platform_device *pdev) } else { led->cdev.name = devm_kasprintf(dev, GFP_KERNEL, "max77650:%s", label); - if (!led->cdev.name) - return -ENOMEM; + if (!led->cdev.name) { + rv = -ENOMEM; + goto err_node_put; + } } of_property_read_string(child, "linux,default-trigger", @@ -116,20 +120,23 @@ static int max77650_led_probe(struct platform_device *pdev) rv = devm_of_led_classdev_register(dev, child, &led->cdev); if (rv) - return rv; + goto err_node_put; rv = regmap_write(map, led->regA, MAX77650_LED_A_DEFAULT); if (rv) - return rv; + goto err_node_put; rv = regmap_write(map, led->regB, MAX77650_LED_B_DEFAULT); if (rv) - return rv; + goto err_node_put; } return regmap_write(map, MAX77650_REG_CNFG_LED_TOP, MAX77650_LED_TOP_DEFAULT); +err_node_put: + of_node_put(child); + return rv; } static struct platform_driver max77650_led_driver = { -- cgit v1.2.3 From 79937a4beeaeb3e2584db5dfe3a7c9ee3d5f97f6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 16 Jul 2019 12:54:24 +0530 Subject: leds: ns2: Add of_node_put() before return Each iteration of for_each_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence create a new label, err_node_put, that puts the previous node before returning the required value. Edit the mid-loop return sites to instead go to this new label. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-ns2.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index f92e2c07c1c6..7c500dfdcfa3 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -245,7 +245,7 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) struct device_node *np = dev->of_node; struct device_node *child; struct ns2_led *led, *leds; - int num_leds = 0; + int ret, num_leds = 0; num_leds = of_get_child_count(np); if (!num_leds) @@ -259,16 +259,16 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) led = leds; for_each_child_of_node(np, child) { const char *string; - int ret, i, num_modes; + int i, num_modes; struct ns2_led_modval *modval; ret = of_get_named_gpio(child, "cmd-gpio", 0); if (ret < 0) - return ret; + goto err_node_put; led->cmd = ret; ret = of_get_named_gpio(child, "slow-gpio", 0); if (ret < 0) - return ret; + goto err_node_put; led->slow = ret; ret = of_property_read_string(child, "label", &string); led->name = (ret == 0) ? string : child->name; @@ -281,7 +281,8 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) if (ret < 0 || ret % 3) { dev_err(dev, "Missing or malformed modes-map property\n"); - return -EINVAL; + ret = -EINVAL; + goto err_node_put; } num_modes = ret / 3; @@ -289,8 +290,10 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) num_modes, sizeof(struct ns2_led_modval), GFP_KERNEL); - if (!modval) - return -ENOMEM; + if (!modval) { + ret = -ENOMEM; + goto err_node_put; + } for (i = 0; i < num_modes; i++) { of_property_read_u32_index(child, @@ -314,6 +317,10 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) pdata->num_leds = num_leds; return 0; + +err_node_put: + of_node_put(child); + return ret; } static const struct of_device_id of_ns2_leds_match[] = { -- cgit v1.2.3 From ed2abfebb041473092b41527903f93390d38afa7 Mon Sep 17 00:00:00 2001 From: Nick Stoughton Date: Wed, 17 Jul 2019 14:56:06 -0700 Subject: leds: leds-lp5562 allow firmware files up to the maximum length Firmware files are in ASCII, using 2 hex characters per byte. The maximum length of a firmware string is therefore 16 (commands) * 2 (bytes per command) * 2 (characters per byte) = 64 Fixes: ff45262a85db ("leds: add new LP5562 LED driver") Signed-off-by: Nick Stoughton Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lp5562.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c index 37632fc63741..edb57c42e8b1 100644 --- a/drivers/leds/leds-lp5562.c +++ b/drivers/leds/leds-lp5562.c @@ -260,7 +260,11 @@ static void lp5562_firmware_loaded(struct lp55xx_chip *chip) { const struct firmware *fw = chip->fw; - if (fw->size > LP5562_PROGRAM_LENGTH) { + /* + * the firmware is encoded in ascii hex character, with 2 chars + * per byte + */ + if (fw->size > (LP5562_PROGRAM_LENGTH * 2)) { dev_err(&chip->cl->dev, "firmware data size overflow: %zu\n", fw->size); return; -- cgit v1.2.3 From f3b357c280738781df3b25c1cbb8166e11982eeb Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 21 Jul 2019 22:59:55 +0200 Subject: leds: an30259a: Fix typo All this file is about an30259a, including the reference to the datasheet at the top of the file. So change the 2 places where an32059a is used instead. Signed-off-by: Christophe JAILLET Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-an30259a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-an30259a.c b/drivers/leds/leds-an30259a.c index 1c1f0c8c56f4..37e7c7998972 100644 --- a/drivers/leds/leds-an30259a.c +++ b/drivers/leds/leds-an30259a.c @@ -353,7 +353,7 @@ MODULE_DEVICE_TABLE(i2c, an30259a_id); static struct i2c_driver an30259a_driver = { .driver = { - .name = "leds-an32059a", + .name = "leds-an30259a", .of_match_table = of_match_ptr(an30259a_match_table), }, .probe_new = an30259a_probe, @@ -364,5 +364,5 @@ static struct i2c_driver an30259a_driver = { module_i2c_driver(an30259a_driver); MODULE_AUTHOR("Simon Shields "); -MODULE_DESCRIPTION("AN32059A LED driver"); +MODULE_DESCRIPTION("AN30259A LED driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 967ea03cc345d86c8e134d7610e61a3012046407 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 21 Jul 2019 23:05:39 +0200 Subject: leds: ktd2692: Fix a typo in the name of a constant There is a typo in KTD2962_MM_MIN_CURR_THRESHOLD_SCALE. 6 and 9 are switched in 2962. Define and use KTD2692_MM_MIN_CURR_THRESHOLD_SCALE instead. Signed-off-by: Christophe JAILLET Acked-by: Pavel Machek Reviewed-by: Enrico Weigelt Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-ktd2692.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/leds-ktd2692.c index f63918206bfb..670efee9b131 100644 --- a/drivers/leds/leds-ktd2692.c +++ b/drivers/leds/leds-ktd2692.c @@ -19,7 +19,7 @@ /* Value related the movie mode */ #define KTD2692_MOVIE_MODE_CURRENT_LEVELS 16 #define KTD2692_MM_TO_FL_RATIO(x) ((x) / 3) -#define KTD2962_MM_MIN_CURR_THRESHOLD_SCALE 8 +#define KTD2692_MM_MIN_CURR_THRESHOLD_SCALE 8 /* Value related the flash mode */ #define KTD2692_FLASH_MODE_TIMEOUT_LEVELS 8 @@ -250,7 +250,7 @@ static void ktd2692_setup(struct ktd2692_context *led) ktd2692_expresswire_reset(led); gpiod_direction_output(led->aux_gpio, KTD2692_LOW); - ktd2692_expresswire_write(led, (KTD2962_MM_MIN_CURR_THRESHOLD_SCALE - 1) + ktd2692_expresswire_write(led, (KTD2692_MM_MIN_CURR_THRESHOLD_SCALE - 1) | KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE); ktd2692_expresswire_write(led, KTD2692_FLASH_MODE_CURR_PERCENT(45) | KTD2692_REG_FLASH_CURRENT_BASE); -- cgit v1.2.3 From 0344e6166bbf90ad3fe05497ffe754bd65f9e7ac Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 15 Jul 2019 16:57:28 +0200 Subject: leds: apu: drop superseeded apu2/3 led support This driver only supports gpio-attached LEDs on apu1/2/3 boards, but neither gpio's themselves, nor other gpio-attached devices (eg. front button). For apu2+ a newer, more complete driver exists, based on a generic driver for the AMD SOCs gpio-controller, supporting LEDs as well other devices. Therefore these boards don't need legacy support from this driver anymore. Both drivers claim the same device, so only one driver may exist in a system, putting distros in the position to decide between either apu2+ keys or apu1 led support. Therefore drop the apu2+ led support from the old driver, solve the conflict and reduce unnecessary code. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/Kconfig | 5 +- drivers/leds/leds-apu.c | 124 +++--------------------------------------------- 2 files changed, 10 insertions(+), 119 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index b0fdeef10bd9..f7a3dd7ecf3d 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -74,9 +74,12 @@ config LEDS_APU depends on LEDS_CLASS depends on X86 && DMI help - This driver makes the PC Engines APU/APU2/APU3 front panel LEDs + This driver makes the PC Engines APU1 front panel LEDs accessible from userspace programs through the LED subsystem. + If you're looking for APU2/3, use the pcengines-apu2 driver. + (symbol CONFIG_PCENGINES_APU2) + To compile this driver as a module, choose M here: the module will be called leds-apu. diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index 8d42e46e2de3..140093a0494d 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -47,12 +47,6 @@ #define APU1_NUM_GPIO 3 #define APU1_IOSIZE sizeof(u8) -#define APU2_FCH_ACPI_MMIO_BASE 0xFED80000 -#define APU2_FCH_GPIO_BASE (APU2_FCH_ACPI_MMIO_BASE + 0x1500) -#define APU2_GPIO_BIT_WRITE 22 -#define APU2_APU2_NUM_GPIO 4 -#define APU2_IOSIZE sizeof(u32) - /* LED access parameters */ struct apu_param { void __iomem *addr; /* for ioread/iowrite */ @@ -75,7 +69,6 @@ struct apu_led_profile { /* Supported platform types */ enum apu_led_platform_types { APU1_LED_PLATFORM, - APU2_LED_PLATFORM, }; struct apu_led_pdata { @@ -96,19 +89,6 @@ static const struct apu_led_profile apu1_led_profile[] = { { "apu:green:3", LED_OFF, APU1_FCH_GPIO_BASE + 2 * APU1_IOSIZE }, }; -static const struct apu_led_profile apu2_led_profile[] = { - { "apu2:green:1", LED_ON, APU2_FCH_GPIO_BASE + 68 * APU2_IOSIZE }, - { "apu2:green:2", LED_OFF, APU2_FCH_GPIO_BASE + 69 * APU2_IOSIZE }, - { "apu2:green:3", LED_OFF, APU2_FCH_GPIO_BASE + 70 * APU2_IOSIZE }, -}; - -/* Same as apu2_led_profile, but with "3" in the LED names. */ -static const struct apu_led_profile apu3_led_profile[] = { - { "apu3:green:1", LED_ON, APU2_FCH_GPIO_BASE + 68 * APU2_IOSIZE }, - { "apu3:green:2", LED_OFF, APU2_FCH_GPIO_BASE + 69 * APU2_IOSIZE }, - { "apu3:green:3", LED_OFF, APU2_FCH_GPIO_BASE + 70 * APU2_IOSIZE }, -}; - static const struct dmi_system_id apu_led_dmi_table[] __initconst = { { .ident = "apu", @@ -117,54 +97,6 @@ static const struct dmi_system_id apu_led_dmi_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "APU") } }, - /* PC Engines APU2 with "Legacy" bios < 4.0.8 */ - { - .ident = "apu2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "APU2") - } - }, - /* PC Engines APU2 with "Legacy" bios >= 4.0.8 */ - { - .ident = "apu2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "apu2") - } - }, - /* PC Engines APU2 with "Mainline" bios */ - { - .ident = "apu2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu2") - } - }, - /* PC Engines APU3 with "Legacy" bios < 4.0.8 */ - { - .ident = "apu3", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "APU3") - } - }, - /* PC Engines APU3 with "Legacy" bios >= 4.0.8 */ - { - .ident = "apu3", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "apu3") - } - }, - /* PC Engines APU2 with "Mainline" bios */ - { - .ident = "apu3", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu3") - } - }, {} }; MODULE_DEVICE_TABLE(dmi, apu_led_dmi_table); @@ -178,25 +110,6 @@ static void apu1_led_brightness_set(struct led_classdev *led, enum led_brightnes spin_unlock(&apu_led->lock); } -static void apu2_led_brightness_set(struct led_classdev *led, enum led_brightness value) -{ - struct apu_led_priv *pled = cdev_to_priv(led); - u32 value_new; - - spin_lock(&apu_led->lock); - - value_new = ioread32(pled->param.addr); - - if (value) - value_new &= ~BIT(APU2_GPIO_BIT_WRITE); - else - value_new |= BIT(APU2_GPIO_BIT_WRITE); - - iowrite32(value_new, pled->param.addr); - - spin_unlock(&apu_led->lock); -} - static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) { int i; @@ -219,8 +132,6 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) led_cdev->flags = LED_CORE_SUSPENDRESUME; if (apu_led->platform == APU1_LED_PLATFORM) led_cdev->brightness_set = apu1_led_brightness_set; - else if (apu_led->platform == APU2_LED_PLATFORM) - led_cdev->brightness_set = apu2_led_brightness_set; pled->param.addr = devm_ioremap(dev, apu_led->profile[i].offset, apu_led->iosize); @@ -254,27 +165,10 @@ static int __init apu_led_probe(struct platform_device *pdev) apu_led->pdev = pdev; - if (dmi_match(DMI_PRODUCT_NAME, "APU")) { - apu_led->profile = apu1_led_profile; - apu_led->platform = APU1_LED_PLATFORM; - apu_led->num_led_instances = ARRAY_SIZE(apu1_led_profile); - apu_led->iosize = APU1_IOSIZE; - } else if (dmi_match(DMI_BOARD_NAME, "APU2") || - dmi_match(DMI_BOARD_NAME, "apu2") || - dmi_match(DMI_BOARD_NAME, "PC Engines apu2")) { - apu_led->profile = apu2_led_profile; - apu_led->platform = APU2_LED_PLATFORM; - apu_led->num_led_instances = ARRAY_SIZE(apu2_led_profile); - apu_led->iosize = APU2_IOSIZE; - } else if (dmi_match(DMI_BOARD_NAME, "APU3") || - dmi_match(DMI_BOARD_NAME, "apu3") || - dmi_match(DMI_BOARD_NAME, "PC Engines apu3")) { - apu_led->profile = apu3_led_profile; - /* Otherwise identical to APU2. */ - apu_led->platform = APU2_LED_PLATFORM; - apu_led->num_led_instances = ARRAY_SIZE(apu3_led_profile); - apu_led->iosize = APU2_IOSIZE; - } + apu_led->profile = apu1_led_profile; + apu_led->platform = APU1_LED_PLATFORM; + apu_led->num_led_instances = ARRAY_SIZE(apu1_led_profile); + apu_led->iosize = APU1_IOSIZE; spin_lock_init(&apu_led->lock); return apu_led_config(&pdev->dev, apu_led); @@ -295,13 +189,7 @@ static int __init apu_led_init(void) pr_err("No PC Engines board detected\n"); return -ENODEV; } - if (!(dmi_match(DMI_PRODUCT_NAME, "APU") || - dmi_match(DMI_PRODUCT_NAME, "APU2") || - dmi_match(DMI_PRODUCT_NAME, "apu2") || - dmi_match(DMI_PRODUCT_NAME, "PC Engines apu2") || - dmi_match(DMI_PRODUCT_NAME, "APU3") || - dmi_match(DMI_PRODUCT_NAME, "apu3") || - dmi_match(DMI_PRODUCT_NAME, "PC Engines apu3"))) { + if (!(dmi_match(DMI_PRODUCT_NAME, "APU"))) { pr_err("Unknown PC Engines board: %s\n", dmi_get_system_info(DMI_PRODUCT_NAME)); return -ENODEV; @@ -337,6 +225,6 @@ module_init(apu_led_init); module_exit(apu_led_exit); MODULE_AUTHOR("Alan Mizrahi"); -MODULE_DESCRIPTION("PC Engines APU family LED driver"); +MODULE_DESCRIPTION("PC Engines APU1 front LED driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:leds_apu"); -- cgit v1.2.3 From da97735cbdb44253b549d6acf8204124de8d72f0 Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 15 Jul 2019 16:57:29 +0200 Subject: leds: apu: drop enum_apu_led_platform_types As this driver now only supports the APU1 boards, we don't need to differenciate between board types anymore. Therefore optimize away the now obsolete code. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-apu.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index 140093a0494d..37b054f76e3d 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -66,16 +66,10 @@ struct apu_led_profile { unsigned long offset; /* for devm_ioremap */ }; -/* Supported platform types */ -enum apu_led_platform_types { - APU1_LED_PLATFORM, -}; - struct apu_led_pdata { struct platform_device *pdev; struct apu_led_priv *pled; const struct apu_led_profile *profile; - enum apu_led_platform_types platform; int num_led_instances; int iosize; /* for devm_ioremap() */ spinlock_t lock; @@ -130,8 +124,7 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) led_cdev->brightness = apu_led->profile[i].brightness; led_cdev->max_brightness = 1; led_cdev->flags = LED_CORE_SUSPENDRESUME; - if (apu_led->platform == APU1_LED_PLATFORM) - led_cdev->brightness_set = apu1_led_brightness_set; + led_cdev->brightness_set = apu1_led_brightness_set; pled->param.addr = devm_ioremap(dev, apu_led->profile[i].offset, apu_led->iosize); @@ -144,7 +137,7 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) if (err) goto error; - led_cdev->brightness_set(led_cdev, apu_led->profile[i].brightness); + apu1_led_brightness_set(led_cdev, apu_led->profile[i].brightness); } return 0; @@ -166,7 +159,6 @@ static int __init apu_led_probe(struct platform_device *pdev) apu_led->pdev = pdev; apu_led->profile = apu1_led_profile; - apu_led->platform = APU1_LED_PLATFORM; apu_led->num_led_instances = ARRAY_SIZE(apu1_led_profile); apu_led->iosize = APU1_IOSIZE; -- cgit v1.2.3 From 08e83826a5ebcaea099a999d4e9915148b78f00a Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 15 Jul 2019 16:57:30 +0200 Subject: leds: apu: drop iosize field from priv data As this driver now only supports the APU1 boards, we don't need to handle different io sizes anymore. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-apu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index 37b054f76e3d..f79146c67132 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -71,7 +71,6 @@ struct apu_led_pdata { struct apu_led_priv *pled; const struct apu_led_profile *profile; int num_led_instances; - int iosize; /* for devm_ioremap() */ spinlock_t lock; }; @@ -127,7 +126,7 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) led_cdev->brightness_set = apu1_led_brightness_set; pled->param.addr = devm_ioremap(dev, - apu_led->profile[i].offset, apu_led->iosize); + apu_led->profile[i].offset, APU1_IOSIZE); if (!pled->param.addr) { err = -ENOMEM; goto error; @@ -160,7 +159,6 @@ static int __init apu_led_probe(struct platform_device *pdev) apu_led->profile = apu1_led_profile; apu_led->num_led_instances = ARRAY_SIZE(apu1_led_profile); - apu_led->iosize = APU1_IOSIZE; spin_lock_init(&apu_led->lock); return apu_led_config(&pdev->dev, apu_led); -- cgit v1.2.3 From cc92e3cce5db4efd6b555102dbf267c8c76bb811 Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 15 Jul 2019 16:57:31 +0200 Subject: leds: apu: drop profile field from priv data As this driver now only supports the APU1 boards, we don't need to handle profiles anymore and just can use the only one global array directly. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-apu.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index f79146c67132..451cb9fe0653 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -69,8 +69,6 @@ struct apu_led_profile { struct apu_led_pdata { struct platform_device *pdev; struct apu_led_priv *pled; - const struct apu_led_profile *profile; - int num_led_instances; spinlock_t lock; }; @@ -109,24 +107,24 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) int err; apu_led->pled = devm_kcalloc(dev, - apu_led->num_led_instances, sizeof(struct apu_led_priv), + ARRAY_SIZE(apu1_led_profile), sizeof(struct apu_led_priv), GFP_KERNEL); if (!apu_led->pled) return -ENOMEM; - for (i = 0; i < apu_led->num_led_instances; i++) { + for (i = 0; i < ARRAY_SIZE(apu1_led_profile); i++) { struct apu_led_priv *pled = &apu_led->pled[i]; struct led_classdev *led_cdev = &pled->cdev; - led_cdev->name = apu_led->profile[i].name; - led_cdev->brightness = apu_led->profile[i].brightness; + led_cdev->name = apu1_led_profile[i].name; + led_cdev->brightness = apu1_led_profile[i].brightness; led_cdev->max_brightness = 1; led_cdev->flags = LED_CORE_SUSPENDRESUME; led_cdev->brightness_set = apu1_led_brightness_set; pled->param.addr = devm_ioremap(dev, - apu_led->profile[i].offset, APU1_IOSIZE); + apu1_led_profile[i].offset, APU1_IOSIZE); if (!pled->param.addr) { err = -ENOMEM; goto error; @@ -136,7 +134,7 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) if (err) goto error; - apu1_led_brightness_set(led_cdev, apu_led->profile[i].brightness); + apu1_led_brightness_set(led_cdev, apu1_led_profile[i].brightness); } return 0; @@ -157,9 +155,6 @@ static int __init apu_led_probe(struct platform_device *pdev) apu_led->pdev = pdev; - apu_led->profile = apu1_led_profile; - apu_led->num_led_instances = ARRAY_SIZE(apu1_led_profile); - spin_lock_init(&apu_led->lock); return apu_led_config(&pdev->dev, apu_led); } @@ -204,7 +199,7 @@ static void __exit apu_led_exit(void) { int i; - for (i = 0; i < apu_led->num_led_instances; i++) + for (i = 0; i < ARRAY_SIZE(apu1_led_profile); i++) led_classdev_unregister(&apu_led->pled[i].cdev); platform_device_unregister(apu_led->pdev); -- cgit v1.2.3 From 93562049a62c5519b3787a428cdd3cfa7fc9e7d4 Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 22 Jul 2019 14:08:51 +0200 Subject: leds: apu: fix error message on probing failure The current error message on failed probing tends to be a bit misleading. Fix it to tell exactly that an APU v1 was not found. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-apu.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index 451cb9fe0653..d794f49f9838 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -170,13 +170,9 @@ static int __init apu_led_init(void) struct platform_device *pdev; int err; - if (!dmi_match(DMI_SYS_VENDOR, "PC Engines")) { - pr_err("No PC Engines board detected\n"); - return -ENODEV; - } - if (!(dmi_match(DMI_PRODUCT_NAME, "APU"))) { - pr_err("Unknown PC Engines board: %s\n", - dmi_get_system_info(DMI_PRODUCT_NAME)); + if (!(dmi_match(DMI_SYS_VENDOR, "PC Engines") && + dmi_match(DMI_PRODUCT_NAME, "APU"))) { + pr_err("No PC Engines APUv1 board detected. For APUv2,3 support, enable CONFIG_PCENGINES_APU2\n"); return -ENODEV; } -- cgit v1.2.3 From 60439711b69b893e84d5bab56de66f9433e68a30 Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 15 Jul 2019 16:57:33 +0200 Subject: leds: apu: add pr_fmt prefix for better log output Define pr_fmt() macro for prefixing the module name to all pr_*() outputs, in order to increase log message clarity. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-apu.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index d794f49f9838..7fd557aceff6 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -31,6 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include -- cgit v1.2.3 From 7d9d60bdfa45181e439b50bb067e97168b99f89e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 20:14:16 +0200 Subject: leds: is31fl319x: simplify getting the adapter of a client We have a dedicated pointer for that, so use it. Much easier to read and less computation involved. Signed-off-by: Wolfram Sang Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-is31fl319x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-is31fl319x.c b/drivers/leds/leds-is31fl319x.c index 2d077b8edd0e..ca6634b8683c 100644 --- a/drivers/leds/leds-is31fl319x.c +++ b/drivers/leds/leds-is31fl319x.c @@ -333,12 +333,11 @@ static int is31fl319x_probe(struct i2c_client *client, { struct is31fl319x_chip *is31; struct device *dev = &client->dev; - struct i2c_adapter *adapter = to_i2c_adapter(dev->parent); int err; int i = 0; u32 aggregated_led_microamp = IS31FL319X_CURRENT_MAX; - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -EIO; is31 = devm_kzalloc(&client->dev, sizeof(*is31), GFP_KERNEL); -- cgit v1.2.3 From b2b998c0f944993c9ef435569651e407d607af41 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:03 +0200 Subject: leds: class: Improve LED and LED flash class registration API Replace of_led_classdev_register() with led_classdev_register_ext(), which accepts easily extendable struct led_init_data, instead of the fixed struct device_node argument. The latter can be now passed in an fwnode property of the struct led_init_data. The modification is driven by the need for passing additional arguments required for the forthcoming generic mechanism for composing LED names. Currently the LED name is conveyed in the "name" char pointer property of the struct led_classdev. This is redundant since LED class device name is accessible throughout the whole LED class device life time via associated struct device's kobj->name property. The change will not break any existing clients since the patch alters also existing led_classdev{_flash}_register() macro wrappers, that pass NULL in place of init_data, which leads to using legacy name initialization path basing on the struct led_classdev's "name" property. Three existing users of devm_of_led_classdev_registers() are modified to use devm_led_classdev_register(), which will not impact their operation since they in fact didn't need to pass struct device_node on registration from the beginning. Signed-off-by: Jacek Anaszewski Cc: Baolin Wang Cc: Dan Murphy Cc: Daniel Mack Cc: Linus Walleij Cc: Oleh Kravchenko Cc: Sakari Ailus Cc: Simon Shields Acked-by: Pavel Machek --- drivers/leds/led-class-flash.c | 9 +++++---- drivers/leds/led-class.c | 29 +++++++++++++++++------------ drivers/leds/leds-cr0014114.c | 3 +-- drivers/leds/leds-gpio.c | 2 +- drivers/leds/leds-max77650.c | 2 +- drivers/leds/leds-pwm.c | 3 +-- 6 files changed, 26 insertions(+), 22 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c index 94980c654d89..60c3de5c6b9f 100644 --- a/drivers/leds/led-class-flash.c +++ b/drivers/leds/led-class-flash.c @@ -282,8 +282,9 @@ static void led_flash_init_sysfs_groups(struct led_classdev_flash *fled_cdev) led_cdev->groups = flash_groups; } -int led_classdev_flash_register(struct device *parent, - struct led_classdev_flash *fled_cdev) +int led_classdev_flash_register_ext(struct device *parent, + struct led_classdev_flash *fled_cdev, + struct led_init_data *init_data) { struct led_classdev *led_cdev; const struct led_flash_ops *ops; @@ -309,13 +310,13 @@ int led_classdev_flash_register(struct device *parent, } /* Register led class device */ - ret = led_classdev_register(parent, led_cdev); + ret = led_classdev_register_ext(parent, led_cdev, init_data); if (ret < 0) return ret; return 0; } -EXPORT_SYMBOL_GPL(led_classdev_flash_register); +EXPORT_SYMBOL_GPL(led_classdev_flash_register_ext); void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev) { diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 4793e77808e2..242122f49333 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -242,14 +243,16 @@ static int led_classdev_next_name(const char *init_name, char *name, } /** - * of_led_classdev_register - register a new object of led_classdev class. + * led_classdev_register_ext - register a new object of led_classdev class + * with init data. * * @parent: parent of LED device * @led_cdev: the led_classdev structure for this device. - * @np: DT node describing this LED + * @init_data: LED class device initialization data */ -int of_led_classdev_register(struct device *parent, struct device_node *np, - struct led_classdev *led_cdev) +int led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data) { char name[LED_MAX_NAME_SIZE]; int ret; @@ -266,7 +269,8 @@ int of_led_classdev_register(struct device *parent, struct device_node *np, mutex_unlock(&led_cdev->led_access); return PTR_ERR(led_cdev->dev); } - led_cdev->dev->of_node = np; + if (init_data && init_data->fwnode) + led_cdev->dev->of_node = to_of_node(init_data->fwnode); if (ret) dev_warn(parent, "Led %s renamed to %s due to name collision", @@ -311,7 +315,7 @@ int of_led_classdev_register(struct device *parent, struct device_node *np, return 0; } -EXPORT_SYMBOL_GPL(of_led_classdev_register); +EXPORT_SYMBOL_GPL(led_classdev_register_ext); /** * led_classdev_unregister - unregisters a object of led_properties class. @@ -356,14 +360,15 @@ static void devm_led_classdev_release(struct device *dev, void *res) } /** - * devm_of_led_classdev_register - resource managed led_classdev_register() + * devm_led_classdev_register_ext - resource managed led_classdev_register_ext() * * @parent: parent of LED device * @led_cdev: the led_classdev structure for this device. + * @init_data: LED class device initialization data */ -int devm_of_led_classdev_register(struct device *parent, - struct device_node *np, - struct led_classdev *led_cdev) +int devm_led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data) { struct led_classdev **dr; int rc; @@ -372,7 +377,7 @@ int devm_of_led_classdev_register(struct device *parent, if (!dr) return -ENOMEM; - rc = of_led_classdev_register(parent, np, led_cdev); + rc = led_classdev_register_ext(parent, led_cdev, init_data); if (rc) { devres_free(dr); return rc; @@ -383,7 +388,7 @@ int devm_of_led_classdev_register(struct device *parent, return 0; } -EXPORT_SYMBOL_GPL(devm_of_led_classdev_register); +EXPORT_SYMBOL_GPL(devm_led_classdev_register_ext); static int devm_led_classdev_match(struct device *dev, void *res, void *data) { diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c index 0e4262462cb9..1c82152764d2 100644 --- a/drivers/leds/leds-cr0014114.c +++ b/drivers/leds/leds-cr0014114.c @@ -207,8 +207,7 @@ static int cr0014114_probe_dt(struct cr0014114 *priv) led->ldev.max_brightness = CR_MAX_BRIGHTNESS; led->ldev.brightness_set_blocking = cr0014114_set_sync; - ret = devm_of_led_classdev_register(priv->dev, np, - &led->ldev); + ret = devm_led_classdev_register(priv->dev, &led->ldev); if (ret) { dev_err(priv->dev, "failed to register LED device %s, err %d", diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index bdc98ddca1dc..8f463c912db8 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -108,7 +108,7 @@ static int create_gpio_led(const struct gpio_led *template, if (ret < 0) return ret; - return devm_of_led_classdev_register(parent, np, &led_dat->cdev); + return devm_led_classdev_register(parent, &led_dat->cdev); } struct gpio_leds_priv { diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 04738324b3e6..5a14f9775b0e 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -118,7 +118,7 @@ static int max77650_led_probe(struct platform_device *pdev) of_property_read_string(child, "linux,default-trigger", &led->cdev.default_trigger); - rv = devm_of_led_classdev_register(dev, child, &led->cdev); + rv = devm_led_classdev_register(dev, &led->cdev); if (rv) goto err_node_put; diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 48d068f80f11..d0e1f2710351 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -111,8 +111,7 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, if (!led_data->period && (led->pwm_period_ns > 0)) led_data->period = led->pwm_period_ns; - ret = devm_of_led_classdev_register(dev, to_of_node(fwnode), - &led_data->cdev); + ret = devm_led_classdev_register(dev, &led_data->cdev); if (ret == 0) { priv->num_leds++; led_pwm_set(&led_data->cdev, led_data->cdev.brightness); -- cgit v1.2.3 From bb4e9af0348dfeafd66c7e7f82e8a0983fe5390c Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: core: Add support for composing LED class device names Add generic support for composing LED class device name. The newly introduced led_compose_name() function composes device name according to either or pattern, depending on the configuration of initialization data. Backward compatibility with in-driver hard-coded LED class device names is assured thanks to the default_label and devicename properties of newly introduced struct led_init_data. In case none of the aforementioned properties was found, then, for OF nodes, the node name is adopted for LED class device name. At the occassion of amending the Documentation/leds/leds-class.txt unify spelling: colour -> color. Alongside these changes added is a new tool - tools/leds/get_led_device_info.sh. The tool allows retrieving details of a LED class device's parent device, which proves that using vendor or product name for devicename part of LED name doesn't convey any added value since that information had been already available in sysfs. The script performs also basic validation of a LED class device name. Signed-off-by: Jacek Anaszewski Cc: Baolin Wang Cc: Dan Murphy Cc: Daniel Mack Cc: Linus Walleij Cc: Oleh Kravchenko Cc: Sakari Ailus Cc: Simon Shields Reviewed-by: Linus Walleij Acked-by: Pavel Machek --- drivers/leds/led-class.c | 20 ++++++-- drivers/leds/led-core.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/leds/leds.h | 1 + 3 files changed, 145 insertions(+), 3 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 242122f49333..508d6477d0b8 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -254,17 +254,31 @@ int led_classdev_register_ext(struct device *parent, struct led_classdev *led_cdev, struct led_init_data *init_data) { - char name[LED_MAX_NAME_SIZE]; + char composed_name[LED_MAX_NAME_SIZE]; + char final_name[LED_MAX_NAME_SIZE]; + const char *proposed_name = composed_name; int ret; - ret = led_classdev_next_name(led_cdev->name, name, sizeof(name)); + if (init_data) { + if (init_data->devname_mandatory && !init_data->devicename) { + dev_err(parent, "Mandatory device name is missing"); + return -EINVAL; + } + ret = led_compose_name(parent, init_data, composed_name); + if (ret < 0) + return ret; + } else { + proposed_name = led_cdev->name; + } + + ret = led_classdev_next_name(proposed_name, final_name, sizeof(final_name)); if (ret < 0) return ret; mutex_init(&led_cdev->led_access); mutex_lock(&led_cdev->led_access); led_cdev->dev = device_create_with_groups(leds_class, parent, 0, - led_cdev, led_cdev->groups, "%s", name); + led_cdev, led_cdev->groups, "%s", final_name); if (IS_ERR(led_cdev->dev)) { mutex_unlock(&led_cdev->led_access); return PTR_ERR(led_cdev->dev); diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index 7107cd7e87cf..f0c1c403f678 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -13,8 +13,10 @@ #include #include #include +#include #include #include +#include #include "leds.h" DECLARE_RWSEM(leds_list_lock); @@ -23,6 +25,18 @@ EXPORT_SYMBOL_GPL(leds_list_lock); LIST_HEAD(leds_list); EXPORT_SYMBOL_GPL(leds_list); +const char * const led_colors[LED_COLOR_ID_MAX] = { + [LED_COLOR_ID_WHITE] = "white", + [LED_COLOR_ID_RED] = "red", + [LED_COLOR_ID_GREEN] = "green", + [LED_COLOR_ID_BLUE] = "blue", + [LED_COLOR_ID_AMBER] = "amber", + [LED_COLOR_ID_VIOLET] = "violet", + [LED_COLOR_ID_YELLOW] = "yellow", + [LED_COLOR_ID_IR] = "ir", +}; +EXPORT_SYMBOL_GPL(led_colors); + static int __led_set_brightness(struct led_classdev *led_cdev, enum led_brightness value) { @@ -353,3 +367,116 @@ void led_sysfs_enable(struct led_classdev *led_cdev) led_cdev->flags &= ~LED_SYSFS_DISABLE; } EXPORT_SYMBOL_GPL(led_sysfs_enable); + +static void led_parse_fwnode_props(struct device *dev, + struct fwnode_handle *fwnode, + struct led_properties *props) +{ + int ret; + + if (!fwnode) + return; + + if (fwnode_property_present(fwnode, "label")) { + ret = fwnode_property_read_string(fwnode, "label", &props->label); + if (ret) + dev_err(dev, "Error parsing 'label' property (%d)\n", ret); + return; + } + + if (fwnode_property_present(fwnode, "color")) { + ret = fwnode_property_read_u32(fwnode, "color", &props->color); + if (ret) + dev_err(dev, "Error parsing 'color' property (%d)\n", ret); + else if (props->color >= LED_COLOR_ID_MAX) + dev_err(dev, "LED color identifier out of range\n"); + else + props->color_present = true; + } + + + if (!fwnode_property_present(fwnode, "function")) + return; + + ret = fwnode_property_read_string(fwnode, "function", &props->function); + if (ret) { + dev_err(dev, + "Error parsing 'function' property (%d)\n", + ret); + } + + if (!fwnode_property_present(fwnode, "function-enumerator")) + return; + + ret = fwnode_property_read_u32(fwnode, "function-enumerator", + &props->func_enum); + if (ret) { + dev_err(dev, + "Error parsing 'function-enumerator' property (%d)\n", + ret); + } else { + props->func_enum_present = true; + } +} + +int led_compose_name(struct device *dev, struct led_init_data *init_data, + char *led_classdev_name) +{ + struct led_properties props = {}; + struct fwnode_handle *fwnode = init_data->fwnode; + const char *devicename = init_data->devicename; + + if (!led_classdev_name) + return -EINVAL; + + led_parse_fwnode_props(dev, fwnode, &props); + + if (props.label) { + /* + * If init_data.devicename is NULL, then it indicates that + * DT label should be used as-is for LED class device name. + * Otherwise the label is prepended with devicename to compose + * the final LED class device name. + */ + if (!devicename) { + strscpy(led_classdev_name, props.label, + LED_MAX_NAME_SIZE); + } else { + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", + devicename, props.label); + } + } else if (props.function || props.color_present) { + char tmp_buf[LED_MAX_NAME_SIZE]; + + if (props.func_enum_present) { + snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s-%d", + props.color_present ? led_colors[props.color] : "", + props.function ?: "", props.func_enum); + } else { + snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s", + props.color_present ? led_colors[props.color] : "", + props.function ?: ""); + } + if (init_data->devname_mandatory) { + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", + devicename, tmp_buf); + } else { + strscpy(led_classdev_name, tmp_buf, LED_MAX_NAME_SIZE); + + } + } else if (init_data->default_label) { + if (!devicename) { + dev_err(dev, "Legacy LED naming requires devicename segment"); + return -EINVAL; + } + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", + devicename, init_data->default_label); + } else if (is_of_node(fwnode)) { + strscpy(led_classdev_name, to_of_node(fwnode)->name, + LED_MAX_NAME_SIZE); + } else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL_GPL(led_compose_name); diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index 47b229469069..0b577cece8f7 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -27,5 +27,6 @@ void led_set_brightness_nosleep(struct led_classdev *led_cdev, extern struct rw_semaphore leds_list_lock; extern struct list_head leds_list; extern struct list_head trigger_list; +extern const char * const led_colors[LED_COLOR_ID_MAX]; #endif /* __LEDS_H_INCLUDED */ -- cgit v1.2.3 From 5fdf85a0911a4109abbb2c006da7d8407cb60078 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: sc27xx-blt: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. Signed-off-by: Jacek Anaszewski Reviewed-by: Baolin Wang Acked-by: Pavel Machek --- drivers/leds/leds-sc27xx-bltc.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-sc27xx-bltc.c b/drivers/leds/leds-sc27xx-bltc.c index fecf27fb1cdc..0ede87420bfc 100644 --- a/drivers/leds/leds-sc27xx-bltc.c +++ b/drivers/leds/leds-sc27xx-bltc.c @@ -6,7 +6,6 @@ #include #include #include -#include /* PMIC global control register definition */ #define SC27XX_MODULE_EN0 0xc08 @@ -46,7 +45,7 @@ #define SC27XX_DELTA_T_MAX (SC27XX_LEDS_STEP * 255) struct sc27xx_led { - char name[LED_MAX_NAME_SIZE]; + struct fwnode_handle *fwnode; struct led_classdev ldev; struct sc27xx_led_priv *priv; u8 line; @@ -249,19 +248,24 @@ static int sc27xx_led_register(struct device *dev, struct sc27xx_led_priv *priv) for (i = 0; i < SC27XX_LEDS_MAX; i++) { struct sc27xx_led *led = &priv->leds[i]; + struct led_init_data init_data = {}; if (!led->active) continue; led->line = i; led->priv = priv; - led->ldev.name = led->name; led->ldev.brightness_set_blocking = sc27xx_led_set; led->ldev.pattern_set = sc27xx_led_pattern_set; led->ldev.pattern_clear = sc27xx_led_pattern_clear; led->ldev.default_trigger = "pattern"; - err = devm_led_classdev_register(dev, &led->ldev); + init_data.fwnode = led->fwnode; + init_data.devicename = "sc27xx"; + init_data.default_label = ":"; + + err = devm_led_classdev_register_ext(dev, &led->ldev, + &init_data); if (err) return err; } @@ -274,7 +278,6 @@ static int sc27xx_led_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node, *child; struct sc27xx_led_priv *priv; - const char *str; u32 base, count, reg; int err; @@ -316,15 +319,8 @@ static int sc27xx_led_probe(struct platform_device *pdev) return -EINVAL; } + priv->leds[reg].fwnode = of_fwnode_handle(child); priv->leds[reg].active = true; - - err = of_property_read_string(child, "label", &str); - if (err) - snprintf(priv->leds[reg].name, LED_MAX_NAME_SIZE, - "sc27xx::"); - else - snprintf(priv->leds[reg].name, LED_MAX_NAME_SIZE, - "sc27xx:%s", str); } err = sc27xx_led_register(dev, priv); -- cgit v1.2.3 From 68e192078e022b8dc0cec57cfdd0e369f62d7ea5 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: lt3593: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. Signed-off-by: Jacek Anaszewski Cc: Daniel Mack Acked-by: Pavel Machek --- drivers/leds/leds-lt3593.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 83e8e58d81cb..c94995f0daa2 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -10,10 +10,10 @@ #include #include #include -#include + +#define LED_LT3593_NAME "lt3593" struct lt3593_led_data { - char name[LED_MAX_NAME_SIZE]; struct led_classdev cdev; struct gpio_desc *gpiod; }; @@ -66,6 +66,7 @@ static int lt3593_led_probe(struct platform_device *pdev) struct lt3593_led_data *led_data; struct fwnode_handle *child; int ret, state = LEDS_GPIO_DEFSTATE_OFF; + struct led_init_data init_data = {}; const char *tmp; if (!dev->of_node) @@ -86,14 +87,6 @@ static int lt3593_led_probe(struct platform_device *pdev) child = device_get_next_child_node(dev, NULL); - ret = fwnode_property_read_string(child, "label", &tmp); - if (ret < 0) - snprintf(led_data->name, sizeof(led_data->name), - "lt3593::"); - else - snprintf(led_data->name, sizeof(led_data->name), - "lt3593:%s", tmp); - fwnode_property_read_string(child, "linux,default-trigger", &led_data->cdev.default_trigger); @@ -102,11 +95,14 @@ static int lt3593_led_probe(struct platform_device *pdev) state = LEDS_GPIO_DEFSTATE_ON; } - led_data->cdev.name = led_data->name; led_data->cdev.brightness_set_blocking = lt3593_led_set; led_data->cdev.brightness = state ? LED_FULL : LED_OFF; - ret = devm_led_classdev_register(dev, &led_data->cdev); + init_data.fwnode = child; + init_data.devicename = LED_LT3593_NAME; + init_data.default_label = ":"; + + ret = devm_led_classdev_register_ext(dev, &led_data->cdev, &init_data); if (ret < 0) { fwnode_handle_put(child); return ret; -- cgit v1.2.3 From 99ca0ea5730971035caa847e5cacf324a2b5598a Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: lp8860: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. While at it, avoid iterating through available child of nodes in favor of obtaining single expected child node using single call to of_get_next_available_child(). Signed-off-by: Jacek Anaszewski Acked-by: Pavel Machek Tested-by: Dan Murphy --- drivers/leds/leds-lp8860.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c index ed680d0c15b0..ac2f5d6272dc 100644 --- a/drivers/leds/leds-lp8860.c +++ b/drivers/leds/leds-lp8860.c @@ -18,7 +18,6 @@ #include #include #include -#include #define LP8860_DISP_CL1_BRT_MSB 0x00 #define LP8860_DISP_CL1_BRT_LSB 0x01 @@ -83,6 +82,8 @@ #define LP8860_CLEAR_FAULTS 0x01 +#define LP8860_NAME "lp8860" + /** * struct lp8860_led - * @lock - Lock for reading/writing the device @@ -92,7 +93,6 @@ * @eeprom_regmap - EEPROM register map * @enable_gpio - VDDIO/EN gpio to enable communication interface * @regulator - LED supply regulator pointer - * @label - LED label */ struct lp8860_led { struct mutex lock; @@ -102,7 +102,6 @@ struct lp8860_led { struct regmap *eeprom_regmap; struct gpio_desc *enable_gpio; struct regulator *regulator; - char label[LED_MAX_NAME_SIZE]; }; struct lp8860_eeprom_reg { @@ -383,25 +382,19 @@ static int lp8860_probe(struct i2c_client *client, struct lp8860_led *led; struct device_node *np = client->dev.of_node; struct device_node *child_node; - const char *name; + struct led_init_data init_data = {}; led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; - for_each_available_child_of_node(np, child_node) { - led->led_dev.default_trigger = of_get_property(child_node, - "linux,default-trigger", - NULL); - - ret = of_property_read_string(child_node, "label", &name); - if (!ret) - snprintf(led->label, sizeof(led->label), "%s:%s", - id->name, name); - else - snprintf(led->label, sizeof(led->label), - "%s::display_cluster", id->name); - } + child_node = of_get_next_available_child(np, NULL); + if (!child_node) + return -EINVAL; + + led->led_dev.default_trigger = of_get_property(child_node, + "linux,default-trigger", + NULL); led->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_LOW); @@ -416,7 +409,6 @@ static int lp8860_probe(struct i2c_client *client, led->regulator = NULL; led->client = client; - led->led_dev.name = led->label; led->led_dev.brightness_set_blocking = lp8860_brightness_set; mutex_init(&led->lock); @@ -443,7 +435,12 @@ static int lp8860_probe(struct i2c_client *client, if (ret) return ret; - ret = devm_led_classdev_register(&client->dev, &led->led_dev); + init_data.fwnode = of_fwnode_handle(child_node); + init_data.devicename = LP8860_NAME; + init_data.default_label = ":display_cluster"; + + ret = devm_led_classdev_register_ext(&client->dev, &led->led_dev, + &init_data); if (ret) { dev_err(&client->dev, "led register err: %d\n", ret); return ret; -- cgit v1.2.3 From a50ff28348934913c46feb7945571329e46c70b3 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: lm3692x: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. At this occassion remove initialization of struct led_classdev's dev->of_node property in the driver, since now it will be taken from fwnode assigned to struct led_init_data and passed to the new devm_led_classdev_register_ext() API. Signed-off-by: Jacek Anaszewski Tested-by: Dan Murphy Acked-by: Pavel Machek --- drivers/leds/leds-lm3692x.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index 4f413a7c5f05..3d381f2f73d0 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -13,7 +13,6 @@ #include #include #include -#include #define LM36922_MODEL 0 #define LM36923_MODEL 1 @@ -103,7 +102,6 @@ * @regmap - Devices register map * @enable_gpio - VDDIO/EN gpio to enable communication interface * @regulator - LED supply regulator pointer - * @label - LED label * @led_enable - LED sync to be enabled * @model_id - Current device model ID enumerated */ @@ -114,7 +112,6 @@ struct lm3692x_led { struct regmap *regmap; struct gpio_desc *enable_gpio; struct regulator *regulator; - char label[LED_MAX_NAME_SIZE]; int led_enable; int model_id; }; @@ -325,7 +322,7 @@ out: static int lm3692x_probe_dt(struct lm3692x_led *led) { struct fwnode_handle *child = NULL; - const char *name; + struct led_init_data init_data = {}; int ret; led->enable_gpio = devm_gpiod_get_optional(&led->client->dev, @@ -350,30 +347,23 @@ static int lm3692x_probe_dt(struct lm3692x_led *led) fwnode_property_read_string(child, "linux,default-trigger", &led->led_dev.default_trigger); - ret = fwnode_property_read_string(child, "label", &name); - if (ret) - snprintf(led->label, sizeof(led->label), - "%s::", led->client->name); - else - snprintf(led->label, sizeof(led->label), - "%s:%s", led->client->name, name); - ret = fwnode_property_read_u32(child, "reg", &led->led_enable); if (ret) { dev_err(&led->client->dev, "reg DT property missing\n"); return ret; } - led->led_dev.name = led->label; + init_data.fwnode = child; + init_data.devicename = led->client->name; + init_data.default_label = ":"; - ret = devm_led_classdev_register(&led->client->dev, &led->led_dev); + ret = devm_led_classdev_register_ext(&led->client->dev, &led->led_dev, + &init_data); if (ret) { dev_err(&led->client->dev, "led register err: %d\n", ret); return ret; } - led->led_dev.dev->of_node = to_of_node(child); - return 0; } -- cgit v1.2.3 From e322b75a301b8cc3915f1e1cbd0e48958b717f6c Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: lm3601x: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. Signed-off-by: Jacek Anaszewski Tested-by: Dan Murphy Acked-by: Pavel Machek --- drivers/leds/leds-lm3601x.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3601x.c b/drivers/leds/leds-lm3601x.c index 081aa71e43a3..b02972f1a341 100644 --- a/drivers/leds/leds-lm3601x.c +++ b/drivers/leds/leds-lm3601x.c @@ -10,7 +10,6 @@ #include #include #include -#include #define LM3601X_LED_IR 0x0 #define LM3601X_LED_TORCH 0x1 @@ -90,8 +89,6 @@ struct lm3601x_led { struct regmap *regmap; struct mutex lock; - char led_name[LED_MAX_NAME_SIZE]; - unsigned int flash_timeout; unsigned int last_flag; @@ -322,10 +319,12 @@ static const struct led_flash_ops flash_ops = { .fault_get = lm3601x_flash_fault_get, }; -static int lm3601x_register_leds(struct lm3601x_led *led) +static int lm3601x_register_leds(struct lm3601x_led *led, + struct fwnode_handle *fwnode) { struct led_classdev *led_cdev; struct led_flash_setting *setting; + struct led_init_data init_data = {}; led->fled_cdev.ops = &flash_ops; @@ -342,20 +341,25 @@ static int lm3601x_register_leds(struct lm3601x_led *led) setting->val = led->flash_current_max; led_cdev = &led->fled_cdev.led_cdev; - led_cdev->name = led->led_name; led_cdev->brightness_set_blocking = lm3601x_brightness_set; led_cdev->max_brightness = DIV_ROUND_UP(led->torch_current_max, LM3601X_TORCH_REG_DIV); led_cdev->flags |= LED_DEV_CAP_FLASH; - return led_classdev_flash_register(&led->client->dev, &led->fled_cdev); + init_data.fwnode = fwnode; + init_data.devicename = led->client->name; + init_data.default_label = (led->led_mode == LM3601X_LED_TORCH) ? + "torch" : "infrared"; + + return led_classdev_flash_register_ext(&led->client->dev, + &led->fled_cdev, &init_data); } -static int lm3601x_parse_node(struct lm3601x_led *led) +static int lm3601x_parse_node(struct lm3601x_led *led, + struct fwnode_handle **fwnode) { struct fwnode_handle *child = NULL; int ret = -ENODEV; - const char *name; child = device_get_next_child_node(&led->client->dev, child); if (!child) { @@ -376,17 +380,6 @@ static int lm3601x_parse_node(struct lm3601x_led *led) goto out_err; } - ret = fwnode_property_read_string(child, "label", &name); - if (ret) { - if (led->led_mode == LM3601X_LED_TORCH) - name = "torch"; - else - name = "infrared"; - } - - snprintf(led->led_name, sizeof(led->led_name), - "%s:%s", led->client->name, name); - ret = fwnode_property_read_u32(child, "led-max-microamp", &led->torch_current_max); if (ret) { @@ -411,6 +404,8 @@ static int lm3601x_parse_node(struct lm3601x_led *led) goto out_err; } + *fwnode = child; + out_err: fwnode_handle_put(child); return ret; @@ -419,6 +414,7 @@ out_err: static int lm3601x_probe(struct i2c_client *client) { struct lm3601x_led *led; + struct fwnode_handle *fwnode; int ret; led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); @@ -428,7 +424,7 @@ static int lm3601x_probe(struct i2c_client *client) led->client = client; i2c_set_clientdata(client, led); - ret = lm3601x_parse_node(led); + ret = lm3601x_parse_node(led, &fwnode); if (ret) return -ENODEV; @@ -442,7 +438,7 @@ static int lm3601x_probe(struct i2c_client *client) mutex_init(&led->lock); - return lm3601x_register_leds(led); + return lm3601x_register_leds(led, fwnode); } static int lm3601x_remove(struct i2c_client *client) -- cgit v1.2.3 From 889003c20602bbebc82a6f32e24e7d0785a7b324 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: cr0014114: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. At this occassion remove initialization of struct led_classdev's dev->of_node property in the driver, since now it will be taken from fwnode assigned to struct led_init_data and passed to the new devm_led_classdev_register_ext() API. Signed-off-by: Jacek Anaszewski Cc: Oleh Kravchenko Acked-by: Pavel Machek --- drivers/leds/leds-cr0014114.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c index 1c82152764d2..2da448ae718e 100644 --- a/drivers/leds/leds-cr0014114.c +++ b/drivers/leds/leds-cr0014114.c @@ -8,7 +8,6 @@ #include #include #include -#include /* * CR0014114 SPI protocol descrtiption: @@ -40,8 +39,9 @@ #define CR_FW_DELAY_MSEC 10 #define CR_RECOUNT_DELAY (HZ * 3600) +#define CR_DEV_NAME "cr0014114" + struct cr0014114_led { - char name[LED_MAX_NAME_SIZE]; struct cr0014114 *priv; struct led_classdev ldev; u8 brightness; @@ -167,8 +167,7 @@ static int cr0014114_set_sync(struct led_classdev *ldev, struct cr0014114_led, ldev); - dev_dbg(led->priv->dev, "Set brightness of %s to %d\n", - led->name, brightness); + dev_dbg(led->priv->dev, "Set brightness to %d\n", brightness); mutex_lock(&led->priv->lock); led->brightness = (u8)brightness; @@ -183,41 +182,32 @@ static int cr0014114_probe_dt(struct cr0014114 *priv) size_t i = 0; struct cr0014114_led *led; struct fwnode_handle *child; - struct device_node *np; + struct led_init_data init_data = {}; int ret; - const char *str; device_for_each_child_node(priv->dev, child) { - np = to_of_node(child); led = &priv->leds[i]; - ret = fwnode_property_read_string(child, "label", &str); - if (ret) - snprintf(led->name, sizeof(led->name), - "cr0014114::"); - else - snprintf(led->name, sizeof(led->name), - "cr0014114:%s", str); - fwnode_property_read_string(child, "linux,default-trigger", &led->ldev.default_trigger); led->priv = priv; - led->ldev.name = led->name; led->ldev.max_brightness = CR_MAX_BRIGHTNESS; led->ldev.brightness_set_blocking = cr0014114_set_sync; - ret = devm_led_classdev_register(priv->dev, &led->ldev); + init_data.fwnode = child; + init_data.devicename = CR_DEV_NAME; + init_data.default_label = ":"; + + ret = devm_led_classdev_register_ext(priv->dev, &led->ldev, + &init_data); if (ret) { dev_err(priv->dev, - "failed to register LED device %s, err %d", - led->name, ret); + "failed to register LED device, err %d", ret); fwnode_handle_put(child); return ret; } - led->ldev.dev->of_node = np; - i++; } -- cgit v1.2.3 From 8103f558527f77e7d36e11cddfbef8bf8c4bae13 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: aat1290: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. After switching to new led_classdev_register_ext() the validity of struct led_classdev's name property is no longer guaranteed, and therefore rely on struct device's kobj.name instead. Signed-off-by: Jacek Anaszewski Acked-by: Pavel Machek --- drivers/leds/leds-aat1290.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c index bf26f5bed1f0..5a0fe7b7b8bc 100644 --- a/drivers/leds/leds-aat1290.c +++ b/drivers/leds/leds-aat1290.c @@ -42,6 +42,8 @@ #define AAT1290_FLASH_TM_NUM_LEVELS 16 #define AAT1290_MM_CURRENT_SCALE_SIZE 15 +#define AAT1290_NAME "aat1290" + struct aat1290_led_config_data { /* maximum LED current in movie mode */ @@ -75,7 +77,6 @@ struct aat1290_led { int *mm_current_scale; /* device mode */ bool movie_mode; - /* brightness cache */ unsigned int torch_brightness; }; @@ -215,7 +216,6 @@ static int aat1290_led_parse_dt(struct aat1290_led *led, struct aat1290_led_config_data *cfg, struct device_node **sub_node) { - struct led_classdev *led_cdev = &led->fled_cdev.led_cdev; struct device *dev = &led->pdev->dev; struct device_node *child_node; #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) @@ -254,9 +254,6 @@ static int aat1290_led_parse_dt(struct aat1290_led *led, return -EINVAL; } - led_cdev->name = of_get_property(child_node, "label", NULL) ? : - child_node->name; - ret = of_property_read_u32(child_node, "led-max-microamp", &cfg->max_mm_current); /* @@ -428,7 +425,7 @@ static void aat1290_init_v4l2_flash_config(struct aat1290_led *led, struct led_classdev *led_cdev = &led->fled_cdev.led_cdev; struct led_flash_setting *s; - strlcpy(v4l2_sd_cfg->dev_name, led_cdev->name, + strlcpy(v4l2_sd_cfg->dev_name, led_cdev->dev->kobj.name, sizeof(v4l2_sd_cfg->dev_name)); s = &v4l2_sd_cfg->intensity; @@ -466,6 +463,7 @@ static int aat1290_led_probe(struct platform_device *pdev) struct aat1290_led *led; struct led_classdev *led_cdev; struct led_classdev_flash *fled_cdev; + struct led_init_data init_data = {}; struct aat1290_led_config_data led_cfg = {}; struct v4l2_flash_config v4l2_sd_cfg = {}; int ret; @@ -494,8 +492,12 @@ static int aat1290_led_probe(struct platform_device *pdev) aat1290_init_flash_timeout(led, &led_cfg); + init_data.fwnode = of_fwnode_handle(sub_node); + init_data.devicename = AAT1290_NAME; + /* Register LED Flash class device */ - ret = led_classdev_flash_register(&pdev->dev, fled_cdev); + ret = led_classdev_flash_register_ext(&pdev->dev, fled_cdev, + &init_data); if (ret < 0) goto err_flash_register; -- cgit v1.2.3 From b1f24498f187cf807faf3b677ffee183a6579a20 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: as3645a: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. After switching to new led_classdev_register_ext() the validity of struct led_classdev's name property is no longer guaranteed, and therefore rely on struct device's kobj.name instead. Signed-off-by: Jacek Anaszewski Cc: Sakari Ailus Acked-by: Pavel Machek --- drivers/leds/leds-as3645a.c | 74 +++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 46 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-as3645a.c b/drivers/leds/leds-as3645a.c index 050088dff8dd..b7e0ae1af8fa 100644 --- a/drivers/leds/leds-as3645a.c +++ b/drivers/leds/leds-as3645a.c @@ -124,11 +124,6 @@ struct as3645a_config { u32 peak; }; -struct as3645a_names { - char flash[32]; - char indicator[32]; -}; - struct as3645a { struct i2c_client *client; @@ -484,12 +479,10 @@ static int as3645a_detect(struct as3645a *flash) } static int as3645a_parse_node(struct as3645a *flash, - struct as3645a_names *names, struct fwnode_handle *fwnode) { struct as3645a_config *cfg = &flash->cfg; struct fwnode_handle *child; - const char *name; int rval; fwnode_for_each_child_node(fwnode, child) { @@ -517,17 +510,6 @@ static int as3645a_parse_node(struct as3645a *flash, return -ENODEV; } - rval = fwnode_property_read_string(flash->flash_node, "label", &name); - if (!rval) { - strlcpy(names->flash, name, sizeof(names->flash)); - } else if (is_of_node(fwnode)) { - snprintf(names->flash, sizeof(names->flash), - "%pOFn:flash", to_of_node(fwnode)); - } else { - dev_err(&flash->client->dev, "flash node has no label!\n"); - return -EINVAL; - } - rval = fwnode_property_read_u32(flash->flash_node, "flash-timeout-us", &cfg->flash_timeout_us); if (rval < 0) { @@ -565,17 +547,6 @@ static int as3645a_parse_node(struct as3645a *flash, goto out_err; } - rval = fwnode_property_read_string(flash->indicator_node, "label", - &name); - if (!rval) { - strlcpy(names->indicator, name, sizeof(names->indicator)); - } else if (is_of_node(fwnode)) { - snprintf(names->indicator, sizeof(names->indicator), - "%pOFn:indicator", to_of_node(fwnode)); - } else { - dev_err(&flash->client->dev, "indicator node has no label!\n"); - return -EINVAL; - } rval = fwnode_property_read_u32(flash->indicator_node, "led-max-microamp", @@ -595,21 +566,25 @@ out_err: return rval; } -static int as3645a_led_class_setup(struct as3645a *flash, - struct as3645a_names *names) +static int as3645a_led_class_setup(struct as3645a *flash) { struct led_classdev *fled_cdev = &flash->fled.led_cdev; struct led_classdev *iled_cdev = &flash->iled_cdev; + struct led_init_data init_data = {}; struct led_flash_setting *cfg; int rval; - iled_cdev->name = names->indicator; iled_cdev->brightness_set_blocking = as3645a_set_indicator_brightness; iled_cdev->max_brightness = flash->cfg.indicator_max_ua / AS_INDICATOR_INTENSITY_STEP; iled_cdev->flags = LED_CORE_SUSPENDRESUME; - rval = led_classdev_register(&flash->client->dev, iled_cdev); + init_data.fwnode = flash->indicator_node; + init_data.devicename = AS_NAME; + init_data.default_label = "indicator"; + + rval = led_classdev_register_ext(&flash->client->dev, iled_cdev, + &init_data); if (rval < 0) return rval; @@ -627,7 +602,6 @@ static int as3645a_led_class_setup(struct as3645a *flash, flash->fled.ops = &as3645a_led_flash_ops; - fled_cdev->name = names->flash; fled_cdev->brightness_set_blocking = as3645a_set_assist_brightness; /* Value 0 is off in LED class. */ fled_cdev->max_brightness = @@ -635,15 +609,23 @@ static int as3645a_led_class_setup(struct as3645a *flash, flash->cfg.assist_max_ua) + 1; fled_cdev->flags = LED_DEV_CAP_FLASH | LED_CORE_SUSPENDRESUME; - rval = led_classdev_flash_register(&flash->client->dev, &flash->fled); - if (rval) { - led_classdev_unregister(iled_cdev); - dev_err(&flash->client->dev, - "led_classdev_flash_register() failed, error %d\n", - rval); - } + init_data.fwnode = flash->flash_node; + init_data.devicename = AS_NAME; + init_data.default_label = "flash"; + + rval = led_classdev_flash_register_ext(&flash->client->dev, + &flash->fled, &init_data); + if (rval) + goto out_err; return rval; + +out_err: + led_classdev_unregister(iled_cdev); + dev_err(&flash->client->dev, + "led_classdev_flash_register() failed, error %d\n", + rval); + return rval; } static int as3645a_v4l2_setup(struct as3645a *flash) @@ -667,8 +649,9 @@ static int as3645a_v4l2_setup(struct as3645a *flash) }, }; - strlcpy(cfg.dev_name, led->name, sizeof(cfg.dev_name)); - strlcpy(cfgind.dev_name, flash->iled_cdev.name, sizeof(cfgind.dev_name)); + strlcpy(cfg.dev_name, led->dev->kobj.name, sizeof(cfg.dev_name)); + strlcpy(cfgind.dev_name, flash->iled_cdev.dev->kobj.name, + sizeof(cfgind.dev_name)); flash->vf = v4l2_flash_init( &flash->client->dev, flash->flash_node, &flash->fled, NULL, @@ -689,7 +672,6 @@ static int as3645a_v4l2_setup(struct as3645a *flash) static int as3645a_probe(struct i2c_client *client) { - struct as3645a_names names; struct as3645a *flash; int rval; @@ -702,7 +684,7 @@ static int as3645a_probe(struct i2c_client *client) flash->client = client; - rval = as3645a_parse_node(flash, &names, dev_fwnode(&client->dev)); + rval = as3645a_parse_node(flash, dev_fwnode(&client->dev)); if (rval < 0) return rval; @@ -717,7 +699,7 @@ static int as3645a_probe(struct i2c_client *client) if (rval) goto out_mutex_destroy; - rval = as3645a_led_class_setup(flash, &names); + rval = as3645a_led_class_setup(flash); if (rval) goto out_mutex_destroy; -- cgit v1.2.3 From d7235f5feaa0d53e27a369a3198827c921103c24 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: gpio: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. Signed-off-by: Jacek Anaszewski Cc: Linus Walleij Acked-by: Pavel Machek --- drivers/leds/leds-gpio.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 8f463c912db8..a5c73f3d5f79 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -73,11 +73,11 @@ static int gpio_blink_set(struct led_classdev *led_cdev, static int create_gpio_led(const struct gpio_led *template, struct gpio_led_data *led_dat, struct device *parent, - struct device_node *np, gpio_blink_set_t blink_set) + struct fwnode_handle *fwnode, gpio_blink_set_t blink_set) { + struct led_init_data init_data = {}; int ret, state; - led_dat->cdev.name = template->name; led_dat->cdev.default_trigger = template->default_trigger; led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod); if (!led_dat->can_sleep) @@ -108,7 +108,16 @@ static int create_gpio_led(const struct gpio_led *template, if (ret < 0) return ret; - return devm_led_classdev_register(parent, &led_dat->cdev); + if (template->name) { + led_dat->cdev.name = template->name; + ret = devm_led_classdev_register(parent, &led_dat->cdev); + } else { + init_data.fwnode = fwnode; + ret = devm_led_classdev_register_ext(parent, &led_dat->cdev, + &init_data); + } + + return ret; } struct gpio_leds_priv { @@ -141,15 +150,6 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) struct gpio_led_data *led_dat = &priv->leds[priv->num_leds]; struct gpio_led led = {}; const char *state = NULL; - struct device_node *np = to_of_node(child); - - ret = fwnode_property_read_string(child, "label", &led.name); - if (ret && IS_ENABLED(CONFIG_OF) && np) - led.name = np->name; - if (!led.name) { - fwnode_handle_put(child); - return ERR_PTR(-EINVAL); - } led.gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child, GPIOD_ASIS, @@ -181,7 +181,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) if (fwnode_property_present(child, "panic-indicator")) led.panic_indicator = 1; - ret = create_gpio_led(&led, led_dat, dev, np, NULL); + ret = create_gpio_led(&led, led_dat, dev, child, NULL); if (ret < 0) { fwnode_handle_put(child); return ERR_PTR(ret); -- cgit v1.2.3 From 1817208e14c6f7b451c64d7127e130e5ed926f54 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: leds: an30259a: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. Signed-off-by: Jacek Anaszewski Cc: Simon Shields Acked-by: Pavel Machek --- drivers/leds/leds-an30259a.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-an30259a.c b/drivers/leds/leds-an30259a.c index 37e7c7998972..250dc9d6f635 100644 --- a/drivers/leds/leds-an30259a.c +++ b/drivers/leds/leds-an30259a.c @@ -13,7 +13,6 @@ #include #include #include -#include #define AN30259A_MAX_LEDS 3 @@ -54,6 +53,8 @@ #define AN30259A_BLINK_MAX_TIME 7500 /* ms */ #define AN30259A_SLOPE_RESOLUTION 500 /* ms */ +#define AN30259A_NAME "an30259a" + #define STATE_OFF 0 #define STATE_KEEP 1 #define STATE_ON 2 @@ -62,11 +63,11 @@ struct an30259a; struct an30259a_led { struct an30259a *chip; + struct fwnode_handle *fwnode; struct led_classdev cdev; u32 num; u32 default_state; bool sloping; - char label[LED_MAX_NAME_SIZE]; }; struct an30259a { @@ -226,14 +227,7 @@ static int an30259a_dt_init(struct i2c_client *client, led->num = source; led->chip = chip; - - if (of_property_read_string(child, "label", &str)) - snprintf(led->label, sizeof(led->label), "an30259a::"); - else - snprintf(led->label, sizeof(led->label), "an30259a:%s", - str); - - led->cdev.name = led->label; + led->fwnode = of_fwnode_handle(child); if (!of_property_read_string(child, "default-state", &str)) { if (!strcmp(str, "on")) @@ -312,13 +306,20 @@ static int an30259a_probe(struct i2c_client *client) chip->regmap = devm_regmap_init_i2c(client, &an30259a_regmap_config); for (i = 0; i < chip->num_leds; i++) { + struct led_init_data init_data = {}; + an30259a_init_default_state(&chip->leds[i]); chip->leds[i].cdev.brightness_set_blocking = an30259a_brightness_set; chip->leds[i].cdev.blink_set = an30259a_blink_set; - err = devm_led_classdev_register(&client->dev, - &chip->leds[i].cdev); + init_data.fwnode = chip->leds[i].fwnode; + init_data.devicename = AN30259A_NAME; + init_data.default_label = ":"; + + err = devm_led_classdev_register_ext(&client->dev, + &chip->leds[i].cdev, + &init_data); if (err < 0) goto exit; } -- cgit v1.2.3 From cc93c86370086519f69aefbbac18375f0b489a0e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 23:14:57 +0300 Subject: leds: lm3532: Switch to use fwnode_property_count_uXX() Use fwnode_property_count_uXX() directly, that makes code neater. Signed-off-by: Andy Shevchenko Acked-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3532.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index 180895b83b88..646100724971 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -549,10 +549,7 @@ static int lm3532_parse_node(struct lm3532_data *priv) lm3532_als_configure(priv, led); } - led->num_leds = fwnode_property_read_u32_array(child, - "led-sources", - NULL, 0); - + led->num_leds = fwnode_property_count_u32(child, "led-sources"); if (led->num_leds > LM3532_MAX_LED_STRINGS) { dev_err(&priv->client->dev, "To many LED string defined\n"); continue; -- cgit v1.2.3 From ebefec8d9fc07eafa7434df1a1c2447b0ea96e50 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 23:14:58 +0300 Subject: leds: lm36274: Switch to use fwnode_property_count_uXX() Use fwnode_property_count_uXX() directly, that makes code neater. Signed-off-by: Andy Shevchenko Acked-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm36274.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm36274.c b/drivers/leds/leds-lm36274.c index ed9dc857ec8f..836b60c9a2b8 100644 --- a/drivers/leds/leds-lm36274.c +++ b/drivers/leds/leds-lm36274.c @@ -90,9 +90,7 @@ static int lm36274_parse_dt(struct lm36274 *lm36274_data) snprintf(label, sizeof(label), "%s:%s", lm36274_data->pdev->name, name); - lm36274_data->num_leds = fwnode_property_read_u32_array(child, - "led-sources", - NULL, 0); + lm36274_data->num_leds = fwnode_property_count_u32(child, "led-sources"); if (lm36274_data->num_leds <= 0) return -ENODEV; -- cgit v1.2.3 From 246eab59eefc26706e59520cf20d2315377efa08 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 23:14:59 +0300 Subject: leds: lm3697: Switch to use fwnode_property_count_uXX() Use fwnode_property_count_uXX() directly, that makes code neater. Signed-off-by: Andy Shevchenko Acked-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3697.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c index 54e0e35df824..b71711aff8a3 100644 --- a/drivers/leds/leds-lm3697.c +++ b/drivers/leds/leds-lm3697.c @@ -244,10 +244,7 @@ static int lm3697_probe_dt(struct lm3697 *priv) led->lmu_data.lsb_brightness_reg = LM3697_CTRL_A_BRT_LSB + led->control_bank * 2; - led->num_leds = fwnode_property_read_u32_array(child, - "led-sources", - NULL, 0); - + led->num_leds = fwnode_property_count_u32(child, "led-sources"); if (led->num_leds > LM3697_MAX_LED_STRINGS) { dev_err(&priv->client->dev, "To many LED strings defined\n"); continue; -- cgit v1.2.3 From 156189a6d7a797d6fa0b13dd6b4f32b11d234a99 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 29 Jul 2019 01:40:15 +0900 Subject: leds: netxbig: remove legacy board-file support Since commit ebc278f15759 ("ARM: mvebu: remove static LED setup for netxbig boards"), no one in upstream passes in the platform data to this driver. Squash leds-kirkwood-netxbig.h into the driver, and remove the legacy board-file support. Link: https://lkml.org/lkml/2019/7/20/83 Suggested-by: Arnd Bergmann Signed-off-by: Masahiro Yamada Signed-off-by: Jacek Anaszewski --- drivers/leds/Kconfig | 1 + drivers/leds/leds-netxbig.c | 70 ++++++++++++++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 20 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index f7a3dd7ecf3d..1988de1d64c0 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -590,6 +590,7 @@ config LEDS_NETXBIG tristate "LED support for Big Network series LEDs" depends on LEDS_CLASS depends on MACH_KIRKWOOD + depends on OF_GPIO default y help This option enables support for LEDs found on the LaCie 2Big diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index 10497a466775..0944cb111c34 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c @@ -15,7 +15,48 @@ #include #include #include -#include + +struct netxbig_gpio_ext { + unsigned int *addr; + int num_addr; + unsigned int *data; + int num_data; + unsigned int enable; +}; + +enum netxbig_led_mode { + NETXBIG_LED_OFF, + NETXBIG_LED_ON, + NETXBIG_LED_SATA, + NETXBIG_LED_TIMER1, + NETXBIG_LED_TIMER2, + NETXBIG_LED_MODE_NUM, +}; + +#define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM + +struct netxbig_led_timer { + unsigned long delay_on; + unsigned long delay_off; + enum netxbig_led_mode mode; +}; + +struct netxbig_led { + const char *name; + const char *default_trigger; + int mode_addr; + int *mode_val; + int bright_addr; + int bright_max; +}; + +struct netxbig_led_platform_data { + struct netxbig_gpio_ext *gpio_ext; + struct netxbig_led_timer *timer; + int num_timer; + struct netxbig_led *leds; + int num_leds; +}; /* * GPIO extension bus. @@ -306,7 +347,6 @@ static int create_netxbig_led(struct platform_device *pdev, return devm_led_classdev_register(&pdev->dev, &led_dat->cdev); } -#ifdef CONFIG_OF_GPIO static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np, struct netxbig_gpio_ext *gpio_ext) { @@ -522,30 +562,20 @@ static const struct of_device_id of_netxbig_leds_match[] = { {}, }; MODULE_DEVICE_TABLE(of, of_netxbig_leds_match); -#else -static inline int -netxbig_leds_get_of_pdata(struct device *dev, - struct netxbig_led_platform_data *pdata) -{ - return -ENODEV; -} -#endif /* CONFIG_OF_GPIO */ static int netxbig_led_probe(struct platform_device *pdev) { - struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct netxbig_led_platform_data *pdata; struct netxbig_led_data *leds_data; int i; int ret; - if (!pdata) { - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - ret = netxbig_leds_get_of_pdata(&pdev->dev, pdata); - if (ret) - return ret; - } + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + ret = netxbig_leds_get_of_pdata(&pdev->dev, pdata); + if (ret) + return ret; leds_data = devm_kcalloc(&pdev->dev, pdata->num_leds, sizeof(*leds_data), @@ -571,7 +601,7 @@ static struct platform_driver netxbig_led_driver = { .probe = netxbig_led_probe, .driver = { .name = "leds-netxbig", - .of_match_table = of_match_ptr(of_netxbig_leds_match), + .of_match_table = of_netxbig_leds_match, }, }; -- cgit v1.2.3 From af7b65054952a9898534d966f2e548d7692b7016 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 29 Jul 2019 12:23:56 +0530 Subject: leds: netxbig: Add of_node_put() in netxbig_leds_get_of_pdata() The variable gpio_ext_np in the function netxbig_leds_get_of_pdata takes the value returned by of_parse_phandle; hence, it must be put in order to prevent a memory leak. Add an of_node_put for gpio_ext_np before a return statement, and move a pre-existing of_node_put statement to right after the last usage of this variable. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-netxbig.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index 0944cb111c34..14ef4ccdda3a 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c @@ -428,12 +428,14 @@ static int netxbig_leds_get_of_pdata(struct device *dev, } gpio_ext = devm_kzalloc(dev, sizeof(*gpio_ext), GFP_KERNEL); - if (!gpio_ext) + if (!gpio_ext) { + of_node_put(gpio_ext_np); return -ENOMEM; + } ret = gpio_ext_get_of_pdata(dev, gpio_ext_np, gpio_ext); + of_node_put(gpio_ext_np); if (ret) return ret; - of_node_put(gpio_ext_np); pdata->gpio_ext = gpio_ext; /* Timers (optional) */ -- cgit v1.2.3 From 6cda08a20dbde45b021091230c8a359fa08c5103 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 23 Jul 2019 23:18:32 +0100 Subject: drivers: Introduce device lookup variants by name Add a helper to match the device name for device lookup. Also reuse this generic exported helper for the existing bus_find_device_by_name(). and add similar variants for driver/class. Cc: Alessandro Zummo Cc: Alexander Aring Cc: Alexander Shishkin Cc: Arnd Bergmann Cc: Dan Murphy Cc: Harald Freudenberger Cc: Heiko Carstens Cc: Jacek Anaszewski Cc: Lee Jones Cc: linux-leds@vger.kernel.org Cc: linux-rtc@vger.kernel.org Cc: linux-usb@vger.kernel.org Cc: linux-wpan@vger.kernel.org Cc: Maxime Coquelin Cc: Pavel Machek Cc: Peter Oberparleiter Cc: "Rafael J. Wysocki" Cc: Stefan Schmidt Cc: Greg Kroah-Hartman Cc: "Rafael J. Wysocki" Signed-off-by: Suzuki K Poulose Reviewed-by: Heikki Krogerus Acked-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190723221838.12024-2-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/leds/led-class.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 4793e77808e2..d54c8e4d8954 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -213,13 +213,6 @@ static int led_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume); -static int match_name(struct device *dev, const void *data) -{ - if (!dev_name(dev)) - return 0; - return !strcmp(dev_name(dev), (char *)data); -} - static int led_classdev_next_name(const char *init_name, char *name, size_t len) { @@ -230,7 +223,7 @@ static int led_classdev_next_name(const char *init_name, char *name, strlcpy(name, init_name, len); while ((ret < len) && - (dev = class_find_device(leds_class, NULL, name, match_name))) { + (dev = class_find_device_by_name(leds_class, name))) { put_device(dev); ret = snprintf(name, len, "%s_%u", init_name, ++i); } -- cgit v1.2.3 From 3881a72f8d0657ca998b217d0a183974ea800401 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Aug 2019 15:20:20 +0200 Subject: leds: pca953x: Include the right header This LED chip provides a GPIO driver, so include rather than the legacy header . Signed-off-by: Linus Walleij Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-pca9532.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 290871072d65..c7c7199e8ebd 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3 From 60e2dde1e91ae0addb21ac380cc36ebee7534e49 Mon Sep 17 00:00:00 2001 From: Wenwen Wang Date: Mon, 19 Aug 2019 15:41:42 -0500 Subject: led: triggers: Fix a memory leak bug In led_trigger_set(), 'event' is allocated in kasprintf(). However, it is not deallocated in the following execution if the label 'err_activate' or 'err_add_groups' is entered, leading to memory leaks. To fix this issue, free 'event' before returning the error. Fixes: 52c47742f79d ("leds: triggers: send uevent when changing triggers") Signed-off-by: Wenwen Wang Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/led-triggers.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/leds') diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 8d11a5e23227..eff1bda8b520 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -173,6 +173,7 @@ err_activate: list_del(&led_cdev->trig_list); write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); led_set_brightness(led_cdev, LED_OFF); + kfree(event); return ret; } -- cgit v1.2.3 From ae6c4c70dfd184f69a24342c09678fb161a7cb4c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 22 Aug 2019 18:19:27 +0300 Subject: leds: max77650: Switch to fwnode property API Switch the max77650 from OF to the fwnode property API. Signed-off-by: Andy Shevchenko Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max77650.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 5a14f9775b0e..4c2d0b3c6dad 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -62,7 +62,7 @@ static int max77650_led_brightness_set(struct led_classdev *cdev, static int max77650_led_probe(struct platform_device *pdev) { - struct device_node *of_node, *child; + struct fwnode_handle *child; struct max77650_led *leds, *led; struct device *dev; struct regmap *map; @@ -71,10 +71,6 @@ static int max77650_led_probe(struct platform_device *pdev) u32 reg; dev = &pdev->dev; - of_node = dev->of_node; - - if (!of_node) - return -ENODEV; leds = devm_kcalloc(dev, sizeof(*leds), MAX77650_LED_NUM_LEDS, GFP_KERNEL); @@ -85,12 +81,12 @@ static int max77650_led_probe(struct platform_device *pdev) if (!map) return -ENODEV; - num_leds = of_get_child_count(of_node); + num_leds = device_get_child_node_count(dev); if (!num_leds || num_leds > MAX77650_LED_NUM_LEDS) return -ENODEV; - for_each_child_of_node(of_node, child) { - rv = of_property_read_u32(child, "reg", ®); + device_for_each_child_node(dev, child) { + rv = fwnode_property_read_u32(child, "reg", ®); if (rv || reg >= MAX77650_LED_NUM_LEDS) { rv = -EINVAL; goto err_node_put; @@ -103,8 +99,8 @@ static int max77650_led_probe(struct platform_device *pdev) led->cdev.brightness_set_blocking = max77650_led_brightness_set; led->cdev.max_brightness = MAX77650_LED_MAX_BRIGHTNESS; - label = of_get_property(child, "label", NULL); - if (!label) { + rv = fwnode_property_read_string(child, "label", &label); + if (rv) { led->cdev.name = "max77650::"; } else { led->cdev.name = devm_kasprintf(dev, GFP_KERNEL, @@ -115,8 +111,8 @@ static int max77650_led_probe(struct platform_device *pdev) } } - of_property_read_string(child, "linux,default-trigger", - &led->cdev.default_trigger); + fwnode_property_read_string(child, "linux,default-trigger", + &led->cdev.default_trigger); rv = devm_led_classdev_register(dev, &led->cdev); if (rv) @@ -135,7 +131,7 @@ static int max77650_led_probe(struct platform_device *pdev) MAX77650_REG_CNFG_LED_TOP, MAX77650_LED_TOP_DEFAULT); err_node_put: - of_node_put(child); + fwnode_handle_put(child); return rv; } -- cgit v1.2.3 From fd81d7e946c6bdb86dbf0bd88fee3e1a545e7979 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 22 Aug 2019 18:19:28 +0300 Subject: leds: Switch to use fwnode instead of be stuck with OF one There is no need to be stuck with OF node when we may use agnostic firmware node instead. It allows users to get property if needed independently of provider. Note, some OF parts are left because %pfw [1] is in progress. [1]: https://lore.kernel.org/patchwork/cover/1054863/ Signed-off-by: Andy Shevchenko Signed-off-by: Jacek Anaszewski --- drivers/leds/led-class.c | 4 ++-- drivers/leds/led-core.c | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index d231240c2047..052c7571e188 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -277,7 +277,7 @@ int led_classdev_register_ext(struct device *parent, return PTR_ERR(led_cdev->dev); } if (init_data && init_data->fwnode) - led_cdev->dev->of_node = to_of_node(init_data->fwnode); + led_cdev->dev->fwnode = init_data->fwnode; if (ret) dev_warn(parent, "Led %s renamed to %s due to name collision", diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index f0c1c403f678..f1f718dbe0f8 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -324,14 +324,11 @@ EXPORT_SYMBOL_GPL(led_update_brightness); u32 *led_get_default_pattern(struct led_classdev *led_cdev, unsigned int *size) { - struct device_node *np = dev_of_node(led_cdev->dev); + struct fwnode_handle *fwnode = led_cdev->dev->fwnode; u32 *pattern; int count; - if (!np) - return NULL; - - count = of_property_count_u32_elems(np, "led-pattern"); + count = fwnode_property_count_u32(fwnode, "led-pattern"); if (count < 0) return NULL; @@ -339,7 +336,7 @@ u32 *led_get_default_pattern(struct led_classdev *led_cdev, unsigned int *size) if (!pattern) return NULL; - if (of_property_read_u32_array(np, "led-pattern", pattern, count)) { + if (fwnode_property_read_u32_array(fwnode, "led-pattern", pattern, count)) { kfree(pattern); return NULL; } -- cgit v1.2.3 From 1312394023dd288946757ba5d7ee89d70709fc33 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Tue, 20 Aug 2019 14:53:03 -0500 Subject: leds: lm3532: Fix brightness control for i2c mode Fix the brightness control for I2C mode. Instead of changing the full scale current register update the ALS target register for the appropriate banks. In addition clean up some code errors and random misspellings found during coding. Tested on Droid4 as well as LM3532 EVM connected to a BeagleBoneBlack Fixes: bc1b8492c764 ("leds: lm3532: Introduce the lm3532 LED driver") Reported-by: Pavel Machek Signed-off-by: Dan Murphy Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3532.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index 646100724971..8132d05f7add 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -38,6 +38,9 @@ #define LM3532_REG_ZN_2_LO 0x65 #define LM3532_REG_ZN_3_HI 0x66 #define LM3532_REG_ZN_3_LO 0x67 +#define LM3532_REG_ZONE_TRGT_A 0x70 +#define LM3532_REG_ZONE_TRGT_B 0x75 +#define LM3532_REG_ZONE_TRGT_C 0x7a #define LM3532_REG_MAX 0x7e /* Contorl Enable */ @@ -116,6 +119,7 @@ struct lm3532_als_data { * @priv - Pointer the device data structure * @control_bank - Control bank the LED is associated to * @mode - Mode of the LED string + * @ctrl_brt_pointer - Zone target register that controls the sink * @num_leds - Number of LED strings are supported in this array * @led_strings - The LED strings supported in this array * @label - LED label @@ -126,6 +130,7 @@ struct lm3532_led { int control_bank; int mode; + int ctrl_brt_pointer; int num_leds; u32 led_strings[LM3532_MAX_CONTROL_BANKS]; char label[LED_MAX_NAME_SIZE]; @@ -339,8 +344,8 @@ static int lm3532_brightness_set(struct led_classdev *led_cdev, if (ret) goto unlock; - brightness_reg = LM3532_REG_CTRL_A_BRT + led->control_bank * 2; - brt_val = brt_val / LM3532_BRT_VAL_ADJUST; + brightness_reg = LM3532_REG_ZONE_TRGT_A + led->control_bank * 5 + + (led->ctrl_brt_pointer >> 2); ret = regmap_write(led->priv->regmap, brightness_reg, brt_val); @@ -356,8 +361,30 @@ static int lm3532_init_registers(struct lm3532_led *led) unsigned int output_cfg_val = 0; unsigned int output_cfg_shift = 0; unsigned int output_cfg_mask = 0; + unsigned int brightness_config_reg; + unsigned int brightness_config_val; int ret, i; + if (drvdata->enable_gpio) + gpiod_direction_output(drvdata->enable_gpio, 1); + + brightness_config_reg = LM3532_REG_ZONE_CFG_A + led->control_bank * 2; + /* + * This could be hard coded to the default value but the control + * brightness register may have changed during boot. + */ + ret = regmap_read(drvdata->regmap, brightness_config_reg, + &led->ctrl_brt_pointer); + if (ret) + return ret; + + led->ctrl_brt_pointer &= LM3532_ZONE_MASK; + brightness_config_val = led->ctrl_brt_pointer | led->mode; + ret = regmap_write(drvdata->regmap, brightness_config_reg, + brightness_config_val); + if (ret) + return ret; + for (i = 0; i < led->num_leds; i++) { output_cfg_shift = led->led_strings[i] * 2; output_cfg_val |= (led->control_bank << output_cfg_shift); @@ -382,7 +409,6 @@ static int lm3532_als_configure(struct lm3532_data *priv, struct lm3532_als_data *als = priv->als_data; u32 als_vmin, als_vmax, als_vstep; int zone_reg = LM3532_REG_ZN_0_HI; - int brightnes_config_reg; int ret; int i; @@ -411,14 +437,7 @@ static int lm3532_als_configure(struct lm3532_data *priv, als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) | (als->als_input_mode << LM3532_ALS_SEL_SHIFT)); - ret = regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config); - if (ret) - return ret; - - brightnes_config_reg = LM3532_REG_ZONE_CFG_A + led->control_bank * 2; - - return regmap_update_bits(priv->regmap, brightnes_config_reg, - LM3532_I2C_CTRL, LM3532_ALS_CTRL); + return regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config); } static int lm3532_parse_als(struct lm3532_data *priv) @@ -634,9 +653,6 @@ static int lm3532_probe(struct i2c_client *client, return ret; } - if (drvdata->enable_gpio) - gpiod_direction_output(drvdata->enable_gpio, 1); - return ret; } -- cgit v1.2.3 From 4c9054506cf970759a9ded0e45c400dd03f37f51 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Tue, 20 Aug 2019 14:53:04 -0500 Subject: leds: lm3532: Change the define for the fs current register Change the define name of the full scale current registers. Signed-off-by: Dan Murphy Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3532.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index 8132d05f7add..0c3d67671ab2 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -23,11 +23,11 @@ #define LM3532_REG_PWM_B_CFG 0x14 #define LM3532_REG_PWM_C_CFG 0x15 #define LM3532_REG_ZONE_CFG_A 0x16 -#define LM3532_REG_CTRL_A_BRT 0x17 +#define LM3532_REG_CTRL_A_FS_CURR 0x17 #define LM3532_REG_ZONE_CFG_B 0x18 -#define LM3532_REG_CTRL_B_BRT 0x19 +#define LM3532_REG_CTRL_B_FS_CURR 0x19 #define LM3532_REG_ZONE_CFG_C 0x1a -#define LM3532_REG_CTRL_C_BRT 0x1b +#define LM3532_REG_CTRL_C_FS_CURR 0x1b #define LM3532_REG_ENABLE 0x1d #define LM3532_ALS_CONFIG 0x23 #define LM3532_REG_ZN_0_HI 0x60 @@ -173,11 +173,11 @@ static const struct reg_default lm3532_reg_defs[] = { {LM3532_REG_PWM_B_CFG, 0x82}, {LM3532_REG_PWM_C_CFG, 0x82}, {LM3532_REG_ZONE_CFG_A, 0xf1}, - {LM3532_REG_CTRL_A_BRT, 0xf3}, + {LM3532_REG_CTRL_A_FS_CURR, 0xf3}, {LM3532_REG_ZONE_CFG_B, 0xf1}, - {LM3532_REG_CTRL_B_BRT, 0xf3}, + {LM3532_REG_CTRL_B_FS_CURR, 0xf3}, {LM3532_REG_ZONE_CFG_C, 0xf1}, - {LM3532_REG_CTRL_C_BRT, 0xf3}, + {LM3532_REG_CTRL_C_FS_CURR, 0xf3}, {LM3532_REG_ENABLE, 0xf8}, {LM3532_ALS_CONFIG, 0x44}, {LM3532_REG_ZN_0_HI, 0x35}, -- cgit v1.2.3 From 6559ac32998248182572e1ccae79dc2eb40ac7c6 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Tue, 20 Aug 2019 14:53:05 -0500 Subject: leds: lm3532: Fixes for the driver for stability Fixed misspelled words, added error check during probe on the init of the registers, and fixed ALS/I2C control mode. Fixes: bc1b8492c764 ("leds: lm3532: Introduce the lm3532 LED driver") Reported-by: Pavel Machek Signed-off-by: Dan Murphy Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3532.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index 0c3d67671ab2..5e33ae4561f2 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -43,7 +43,7 @@ #define LM3532_REG_ZONE_TRGT_C 0x7a #define LM3532_REG_MAX 0x7e -/* Contorl Enable */ +/* Control Enable */ #define LM3532_CTRL_A_ENABLE BIT(0) #define LM3532_CTRL_B_ENABLE BIT(1) #define LM3532_CTRL_C_ENABLE BIT(2) @@ -307,7 +307,7 @@ static int lm3532_led_disable(struct lm3532_led *led_data) int ret; ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE, - ctrl_en_val, ~ctrl_en_val); + ctrl_en_val, 0); if (ret) { dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret); return ret; @@ -326,7 +326,7 @@ static int lm3532_brightness_set(struct led_classdev *led_cdev, mutex_lock(&led->priv->lock); - if (led->mode == LM3532_BL_MODE_ALS) { + if (led->mode == LM3532_ALS_CTRL) { if (brt_val > LED_OFF) ret = lm3532_led_enable(led); else @@ -561,11 +561,14 @@ static int lm3532_parse_node(struct lm3532_data *priv) } if (led->mode == LM3532_BL_MODE_ALS) { + led->mode = LM3532_ALS_CTRL; ret = lm3532_parse_als(priv); if (ret) dev_err(&priv->client->dev, "Failed to parse als\n"); else lm3532_als_configure(priv, led); + } else { + led->mode = LM3532_I2C_CTRL; } led->num_leds = fwnode_property_count_u32(child, "led-sources"); @@ -606,7 +609,13 @@ static int lm3532_parse_node(struct lm3532_data *priv) goto child_out; } - lm3532_init_registers(led); + ret = lm3532_init_registers(led); + if (ret) { + dev_err(&priv->client->dev, "register init err: %d\n", + ret); + fwnode_handle_put(child); + goto child_out; + } i++; } -- cgit v1.2.3 From 517ea49a7b23c6730ed1a23f152fcd32173eb300 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Tue, 20 Aug 2019 14:53:07 -0500 Subject: leds: lm3532: Add full scale current configuration Allow the full scale current to be configured at init. Valid rangles are 5mA->29.8mA. Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3532.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index 5e33ae4561f2..ba352d76a8fb 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -89,6 +89,10 @@ #define LM3532_NUM_AVG_VALS 8 #define LM3532_NUM_IMP_VALS 32 +#define LM3532_FS_CURR_MIN 5000 +#define LM3532_FS_CURR_MAX 29800 +#define LM3532_FS_CURR_STEP 800 + /* * struct lm3532_als_data * @config - value of ALS configuration register @@ -121,6 +125,7 @@ struct lm3532_als_data { * @mode - Mode of the LED string * @ctrl_brt_pointer - Zone target register that controls the sink * @num_leds - Number of LED strings are supported in this array + * @full_scale_current - The full-scale current setting for the current sink. * @led_strings - The LED strings supported in this array * @label - LED label */ @@ -132,6 +137,7 @@ struct lm3532_led { int mode; int ctrl_brt_pointer; int num_leds; + int full_scale_current; u32 led_strings[LM3532_MAX_CONTROL_BANKS]; char label[LED_MAX_NAME_SIZE]; }; @@ -363,6 +369,8 @@ static int lm3532_init_registers(struct lm3532_led *led) unsigned int output_cfg_mask = 0; unsigned int brightness_config_reg; unsigned int brightness_config_val; + int fs_current_reg; + int fs_current_val; int ret, i; if (drvdata->enable_gpio) @@ -385,6 +393,17 @@ static int lm3532_init_registers(struct lm3532_led *led) if (ret) return ret; + if (led->full_scale_current) { + fs_current_reg = LM3532_REG_CTRL_A_FS_CURR + led->control_bank * 2; + fs_current_val = (led->full_scale_current - LM3532_FS_CURR_MIN) / + LM3532_FS_CURR_STEP; + + ret = regmap_write(drvdata->regmap, fs_current_reg, + fs_current_val); + if (ret) + return ret; + } + for (i = 0; i < led->num_leds; i++) { output_cfg_shift = led->led_strings[i] * 2; output_cfg_val |= (led->control_bank << output_cfg_shift); @@ -560,6 +579,12 @@ static int lm3532_parse_node(struct lm3532_data *priv) goto child_out; } + ret = fwnode_property_read_u32(child, "led-max-microamp", + &led->full_scale_current); + + if (led->full_scale_current > LM3532_FS_CURR_MAX) + led->full_scale_current = LM3532_FS_CURR_MAX; + if (led->mode == LM3532_BL_MODE_ALS) { led->mode = LM3532_ALS_CTRL; ret = lm3532_parse_als(priv); -- cgit v1.2.3 From 1dbb9fb4082ce2a2f1cf9596881ddece062d15d0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Aug 2019 13:52:29 +0300 Subject: leds: Allow to call led_classdev_unregister() unconditionally If in the certain driver the LED is optional, and it's a majority of them, the call of led_classdev_unregister() still requires some additional checks. The usual pattern on unregistering is to check for NULL, but we also check for IS_ERR() in case device_create_with_groups() fails. The change will reduce a burden in a lot of drivers to repeatedly check for above conditions. Signed-off-by: Andy Shevchenko Signed-off-by: Jacek Anaszewski --- drivers/leds/led-class.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/leds') diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 052c7571e188..647b1263c579 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -287,6 +287,7 @@ int led_classdev_register_ext(struct device *parent, ret = led_add_brightness_hw_changed(led_cdev); if (ret) { device_unregister(led_cdev->dev); + led_cdev->dev = NULL; mutex_unlock(&led_cdev->led_access); return ret; } @@ -332,6 +333,9 @@ EXPORT_SYMBOL_GPL(led_classdev_register_ext); */ void led_classdev_unregister(struct led_classdev *led_cdev) { + if (IS_ERR_OR_NULL(led_cdev->dev)) + return; + #ifdef CONFIG_LEDS_TRIGGERS down_write(&led_cdev->trigger_lock); if (led_cdev->trigger) -- cgit v1.2.3 From 68bfcf6debd72121758d6e0fbf75f506126d7b9a Mon Sep 17 00:00:00 2001 From: Alexander Dahl Date: Tue, 27 Aug 2019 15:00:27 +0200 Subject: leds: syscon: Use resource managed variant of device register We have a MFD driver compiled as module instantiating this driver. When unloading that module, those LED devices are not removed, which produces conflicts, when that module is inserted again. Signed-off-by: Alexander Dahl Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-syscon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-syscon.c b/drivers/leds/leds-syscon.c index e35dff0050f0..b58f3cafe16f 100644 --- a/drivers/leds/leds-syscon.c +++ b/drivers/leds/leds-syscon.c @@ -115,7 +115,7 @@ static int syscon_led_probe(struct platform_device *pdev) } sled->cdev.brightness_set = syscon_led_set; - ret = led_classdev_register(dev, &sled->cdev); + ret = devm_led_classdev_register(dev, &sled->cdev); if (ret < 0) return ret; -- cgit v1.2.3 From 070a0eed7580a976b397dce981db9746df714327 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 27 Aug 2019 14:52:05 -0700 Subject: leds: lm3532: Avoid potentially unpaired regulator calls We may currently get unpaired regulator calls when configuring the LED brightness via sysfs in case of regulator calls producing errors. Let's fix this by maintaining local state for enabled. Signed-off-by: Tony Lindgren Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3532.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index ba352d76a8fb..c5cfd8e3f15f 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -127,6 +127,7 @@ struct lm3532_als_data { * @num_leds - Number of LED strings are supported in this array * @full_scale_current - The full-scale current setting for the current sink. * @led_strings - The LED strings supported in this array + * @enabled - Enabled status * @label - LED label */ struct lm3532_led { @@ -138,6 +139,7 @@ struct lm3532_led { int ctrl_brt_pointer; int num_leds; int full_scale_current; + int enabled:1; u32 led_strings[LM3532_MAX_CONTROL_BANKS]; char label[LED_MAX_NAME_SIZE]; }; @@ -292,11 +294,15 @@ static int lm3532_get_ramp_index(int ramp_time) ramp_time); } +/* Caller must take care of locking */ static int lm3532_led_enable(struct lm3532_led *led_data) { int ctrl_en_val = BIT(led_data->control_bank); int ret; + if (led_data->enabled) + return 0; + ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE, ctrl_en_val, ctrl_en_val); if (ret) { @@ -304,14 +310,24 @@ static int lm3532_led_enable(struct lm3532_led *led_data) return ret; } - return regulator_enable(led_data->priv->regulator); + ret = regulator_enable(led_data->priv->regulator); + if (ret < 0) + return ret; + + led_data->enabled = 1; + + return 0; } +/* Caller must take care of locking */ static int lm3532_led_disable(struct lm3532_led *led_data) { int ctrl_en_val = BIT(led_data->control_bank); int ret; + if (!led_data->enabled) + return 0; + ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE, ctrl_en_val, 0); if (ret) { @@ -319,7 +335,13 @@ static int lm3532_led_disable(struct lm3532_led *led_data) return ret; } - return regulator_disable(led_data->priv->regulator); + ret = regulator_disable(led_data->priv->regulator); + if (ret < 0) + return ret; + + led_data->enabled = 0; + + return 0; } static int lm3532_brightness_set(struct led_classdev *led_cdev, -- cgit v1.2.3 From 2637fd436c60c599e0967faee1903cce58c4a7f9 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Wed, 28 Aug 2019 10:22:19 -0500 Subject: leds: ti-lmu-common: Fix coccinelle issue in TI LMU Fix the coccinelle issues found in the TI LMU common code drivers/leds/leds-ti-lmu-common.c:97:20-29: WARNING: Unsigned expression compared with zero: ramp_down < 0 drivers/leds/leds-ti-lmu-common.c:97:5-12: WARNING: Unsigned expression compared with zero: ramp_up < 0 Fixes: 3fce8e1eb994 ("leds: TI LMU: Add common code for TI LMU devices") Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-ti-lmu-common.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-ti-lmu-common.c b/drivers/leds/leds-ti-lmu-common.c index adc7293004f1..e294a0b097e3 100644 --- a/drivers/leds/leds-ti-lmu-common.c +++ b/drivers/leds/leds-ti-lmu-common.c @@ -11,10 +11,10 @@ #include -const static int ramp_table[16] = {2048, 262000, 524000, 1049000, 2090000, - 4194000, 8389000, 16780000, 33550000, 41940000, - 50330000, 58720000, 67110000, 83880000, - 100660000, 117440000}; +const static unsigned int ramp_table[16] = {2048, 262000, 524000, 1049000, + 2090000, 4194000, 8389000, 16780000, 33550000, + 41940000, 50330000, 58720000, 67110000, + 83880000, 100660000, 117440000}; static int ti_lmu_common_update_brightness(struct ti_lmu_bank *lmu_bank, int brightness) @@ -54,7 +54,7 @@ int ti_lmu_common_set_brightness(struct ti_lmu_bank *lmu_bank, int brightness) } EXPORT_SYMBOL(ti_lmu_common_set_brightness); -static int ti_lmu_common_convert_ramp_to_index(unsigned int usec) +static unsigned int ti_lmu_common_convert_ramp_to_index(unsigned int usec) { int size = ARRAY_SIZE(ramp_table); int i; @@ -78,7 +78,7 @@ static int ti_lmu_common_convert_ramp_to_index(unsigned int usec) } } - return -EINVAL; + return 0; } int ti_lmu_common_set_ramp(struct ti_lmu_bank *lmu_bank) @@ -94,9 +94,6 @@ int ti_lmu_common_set_ramp(struct ti_lmu_bank *lmu_bank) ramp_down = ti_lmu_common_convert_ramp_to_index(lmu_bank->ramp_down_usec); } - if (ramp_up < 0 || ramp_down < 0) - return -EINVAL; - ramp = (ramp_up << 4) | ramp_down; return regmap_write(regmap, lmu_bank->runtime_ramp_reg, ramp); -- cgit v1.2.3 From 1669ec78b87c0f04c963a5fc0885505d97468c7a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 30 Aug 2019 13:14:48 -0500 Subject: leds: is31fl32xx: Use struct_size() helper One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct is31fl32xx_priv { ... struct is31fl32xx_led_data leds[0]; }; Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes. So, replace the following function: static inline size_t sizeof_is31fl32xx_priv(int num_leds) { return sizeof(struct is31fl32xx_priv) + (sizeof(struct is31fl32xx_led_data) * num_leds); } with: struct_size(priv, leds, count) This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-is31fl32xx.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-is31fl32xx.c b/drivers/leds/leds-is31fl32xx.c index 6fbab70dfb04..6f29b8943913 100644 --- a/drivers/leds/leds-is31fl32xx.c +++ b/drivers/leds/leds-is31fl32xx.c @@ -324,12 +324,6 @@ static int is31fl32xx_init_regs(struct is31fl32xx_priv *priv) return 0; } -static inline size_t sizeof_is31fl32xx_priv(int num_leds) -{ - return sizeof(struct is31fl32xx_priv) + - (sizeof(struct is31fl32xx_led_data) * num_leds); -} - static int is31fl32xx_parse_child_dt(const struct device *dev, const struct device_node *child, struct is31fl32xx_led_data *led_data) @@ -450,7 +444,7 @@ static int is31fl32xx_probe(struct i2c_client *client, if (!count) return -EINVAL; - priv = devm_kzalloc(dev, sizeof_is31fl32xx_priv(count), + priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL); if (!priv) return -ENOMEM; -- cgit v1.2.3 From d4b02200ae7cc5886be01c0d7f1d335f4b6966a7 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 29 Aug 2019 19:53:20 -0500 Subject: leds: pwm: Use struct_size() helper One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct led_pwm_priv { ... struct led_pwm_data leds[0]; }; Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes. So, replace the following function: static inline size_t sizeof_pwm_leds_priv(int num_leds) { return sizeof(struct led_pwm_priv) + (sizeof(struct led_pwm_data) * num_leds); } with: struct_size(priv, leds, count) This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-pwm.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index d0e1f2710351..8b6965a563e9 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -65,12 +65,6 @@ static int led_pwm_set(struct led_classdev *led_cdev, return 0; } -static inline size_t sizeof_pwm_leds_priv(int num_leds) -{ - return sizeof(struct led_pwm_priv) + - (sizeof(struct led_pwm_data) * num_leds); -} - static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, struct led_pwm *led, struct fwnode_handle *fwnode) { @@ -174,7 +168,7 @@ static int led_pwm_probe(struct platform_device *pdev) if (!count) return -EINVAL; - priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(count), + priv = devm_kzalloc(&pdev->dev, struct_size(priv, leds, count), GFP_KERNEL); if (!priv) return -ENOMEM; -- cgit v1.2.3 From 4e4210402639f16dfbfa5ba277aeb88fff401cec Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 30 Aug 2019 18:08:19 +0300 Subject: leds: trigger: gpio: GPIO 0 is valid Allow all valid GPIOs to be used in the driver. Fixes: 17354bfe8527 ("leds: Add gpio-led trigger") Signed-off-by: Andy Shevchenko Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-gpio.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/trigger/ledtrig-gpio.c b/drivers/leds/trigger/ledtrig-gpio.c index 33cc99a1a16a..dc64679b1a92 100644 --- a/drivers/leds/trigger/ledtrig-gpio.c +++ b/drivers/leds/trigger/ledtrig-gpio.c @@ -131,10 +131,10 @@ static ssize_t gpio_trig_gpio_store(struct device *dev, if (gpio_data->gpio == gpio) return n; - if (!gpio) { - if (gpio_data->gpio != 0) + if (!gpio_is_valid(gpio)) { + if (gpio_is_valid(gpio_data->gpio)) free_irq(gpio_to_irq(gpio_data->gpio), led); - gpio_data->gpio = 0; + gpio_data->gpio = gpio; return n; } @@ -144,7 +144,7 @@ static ssize_t gpio_trig_gpio_store(struct device *dev, if (ret) { dev_err(dev, "request_irq failed with error %d\n", ret); } else { - if (gpio_data->gpio != 0) + 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. */ @@ -172,6 +172,8 @@ static int gpio_trig_activate(struct led_classdev *led) return -ENOMEM; gpio_data->led = led; + gpio_data->gpio = -ENOENT; + led_set_trigger_data(led, gpio_data); return 0; @@ -181,7 +183,7 @@ static void gpio_trig_deactivate(struct led_classdev *led) { struct gpio_trig_data *gpio_data = led_get_trigger_data(led); - if (gpio_data->gpio != 0) + if (gpio_is_valid(gpio_data->gpio)) free_irq(gpio_to_irq(gpio_data->gpio), led); kfree(gpio_data); } -- cgit v1.2.3 From 536129cc9a26a47ebda5123c992a875d7f81a746 Mon Sep 17 00:00:00 2001 From: Krzysztof Wilczynski Date: Fri, 30 Aug 2019 20:11:03 +0200 Subject: leds: lm3532: Move static keyword to the front of declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the static keyword to the front of declarations ramp_table, als_avrg_table and als_imp_table, and resolve the following compiler warnings that can be seen when building with warnings enabled (W=1): drivers/leds/leds-lm3532.c:209:1: warning: ‘static’ is not at beginning of declaration [-Wold-style-declaration] drivers/leds/leds-lm3532.c:266:1: warning: ‘static’ is not at beginning of declaration [-Wold-style-declaration] drivers/leds/leds-lm3532.c:281:1: warning: ‘static’ is not at beginning of declaration [-Wold-style-declaration] Signed-off-by: Krzysztof Wilczynski Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3532.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index c5cfd8e3f15f..62ace6698d25 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -208,7 +208,7 @@ static const struct regmap_config lm3532_regmap_config = { .cache_type = REGCACHE_FLAT, }; -const static int als_imp_table[LM3532_NUM_IMP_VALS] = {37000, 18500, 12330, +static const int als_imp_table[LM3532_NUM_IMP_VALS] = {37000, 18500, 12330, 92500, 7400, 6170, 5290, 4630, 4110, 3700, 3360, 3080, 2850, 2640, 2440, @@ -265,7 +265,7 @@ static int lm3532_get_index(const int table[], int size, int value) return -EINVAL; } -const static int als_avrg_table[LM3532_NUM_AVG_VALS] = {17920, 35840, 71680, +static const int als_avrg_table[LM3532_NUM_AVG_VALS] = {17920, 35840, 71680, 1433360, 286720, 573440, 1146880, 2293760}; static int lm3532_get_als_avg_index(int avg_time) @@ -280,7 +280,7 @@ static int lm3532_get_als_avg_index(int avg_time) avg_time); } -const static int ramp_table[LM3532_NUM_RAMP_VALS] = { 8, 1024, 2048, 4096, 8192, +static const int ramp_table[LM3532_NUM_RAMP_VALS] = { 8, 1024, 2048, 4096, 8192, 16384, 32768, 65536}; static int lm3532_get_ramp_index(int ramp_time) { -- cgit v1.2.3 From ba7eb84f71692d6ece8d5782ab1658fe7f6c0cad Mon Sep 17 00:00:00 2001 From: Krzysztof Wilczynski Date: Fri, 30 Aug 2019 20:11:04 +0200 Subject: leds: ti-lmu-common: Move static keyword to the front of declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the static keyword to the front of declaration of ramp_table, and resolve the following compiler warning that can be seen when building with warnings enabled (W=1): drivers/leds/leds-ti-lmu-common.c:14:1: warning: ‘static’ is not at beginning of declaration [-Wold-style-declaration] Signed-off-by: Krzysztof Wilczynski Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-ti-lmu-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-ti-lmu-common.c b/drivers/leds/leds-ti-lmu-common.c index e294a0b097e3..d7f10ad721ba 100644 --- a/drivers/leds/leds-ti-lmu-common.c +++ b/drivers/leds/leds-ti-lmu-common.c @@ -11,7 +11,7 @@ #include -const static unsigned int ramp_table[16] = {2048, 262000, 524000, 1049000, +static const unsigned int ramp_table[16] = {2048, 262000, 524000, 1049000, 2090000, 4194000, 8389000, 16780000, 33550000, 41940000, 50330000, 58720000, 67110000, 83880000, 100660000, 117440000}; -- cgit v1.2.3 From 4016ba85880b252365d11bc7dc899450f2c73ad7 Mon Sep 17 00:00:00 2001 From: Oleh Kravchenko Date: Wed, 4 Sep 2019 00:18:19 +0300 Subject: led: triggers: Fix dereferencing of null pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Error was detected by PVS-Studio: V522 Dereferencing of the null pointer 'led_cdev->trigger' might take place. Fixes: 2282e125a406 ("leds: triggers: let struct led_trigger::activate() return an error code") Signed-off-by: Oleh Kravchenko Reviewed-by: Uwe Kleine-König Signed-off-by: Jacek Anaszewski --- drivers/leds/led-triggers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index eff1bda8b520..23963e5cb5d6 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -167,11 +167,11 @@ err_add_groups: trig->deactivate(led_cdev); err_activate: - led_cdev->trigger = NULL; - led_cdev->trigger_data = NULL; write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); list_del(&led_cdev->trig_list); write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); + led_cdev->trigger = NULL; + led_cdev->trigger_data = NULL; led_set_brightness(led_cdev, LED_OFF); kfree(event); -- cgit v1.2.3 From 6d4faf3b6b6eb3c8a750b2e6659a5b1ff3dd9e75 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Wed, 11 Sep 2019 13:27:30 -0500 Subject: leds: lm3532: Fix optional led-max-microamp prop error handling Fix the error handling for the led-max-microamp property. Need to check if the property is present and then if it is retrieve the setting and its max boundary Reported-by: Pavel Machek Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3532.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index 62ace6698d25..0507c6575c08 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -601,11 +601,14 @@ static int lm3532_parse_node(struct lm3532_data *priv) goto child_out; } - ret = fwnode_property_read_u32(child, "led-max-microamp", - &led->full_scale_current); - - if (led->full_scale_current > LM3532_FS_CURR_MAX) - led->full_scale_current = LM3532_FS_CURR_MAX; + if (fwnode_property_present(child, "led-max-microamp") && + fwnode_property_read_u32(child, "led-max-microamp", + &led->full_scale_current)) + dev_err(&priv->client->dev, + "Failed getting led-max-microamp\n"); + else + led->full_scale_current = min(led->full_scale_current, + LM3532_FS_CURR_MAX); if (led->mode == LM3532_BL_MODE_ALS) { led->mode = LM3532_ALS_CTRL; -- cgit v1.2.3