From aa4e2524955971730ff845c0589f2f8f441ad610 Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Fri, 4 Sep 2015 12:12:01 +0200 Subject: leds: leds-cobalt-qube: Use devm_led_classdev_register Use resource-managed function devm_led_classdev_register instead of led_classdev_register to make the error-path simpler. To be compatible with the change, goto is replaced with direct return, unneeded label err_null is dropped and unnecessary variable retval is removed. Also, remove redundant cobalt_qube_led_remove. Signed-off-by: Vaishali Thakkar Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c index d975220..9be1957 100644 --- a/drivers/leds/leds-cobalt-qube.c +++ b/drivers/leds/leds-cobalt-qube.c @@ -36,7 +36,6 @@ static struct led_classdev qube_front_led = { static int cobalt_qube_led_probe(struct platform_device *pdev) { struct resource *res; - int retval; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -49,31 +48,11 @@ static int cobalt_qube_led_probe(struct platform_device *pdev) led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT; writeb(led_value, led_port); - retval = led_classdev_register(&pdev->dev, &qube_front_led); - if (retval) - goto err_null; - - return 0; - -err_null: - led_port = NULL; - - return retval; -} - -static int cobalt_qube_led_remove(struct platform_device *pdev) -{ - led_classdev_unregister(&qube_front_led); - - if (led_port) - led_port = NULL; - - return 0; + return devm_led_classdev_register(&pdev->dev, &qube_front_led); } static struct platform_driver cobalt_qube_led_driver = { .probe = cobalt_qube_led_probe, - .remove = cobalt_qube_led_remove, .driver = { .name = "cobalt-qube-leds", }, -- cgit v0.10.2 From c0fc68ba97b0f96fa4aaa6010ead6b77d3ffc3dd Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Sun, 6 Sep 2015 01:23:37 +0530 Subject: leds: leds-hp6xx: Use devm_led_classdev_register Use resource-managed function devm_led_classdev_register instead of led_classdev_register to simplify error path. An unnecessary check of ret is replaced with a direct return Also, remove redundant hp6xxled_remove. Signed-off-by: Muhammad Falak R Wani Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c index 0b84c01..a6b8db0 100644 --- a/drivers/leds/leds-hp6xx.c +++ b/drivers/leds/leds-hp6xx.c @@ -59,28 +59,15 @@ static int hp6xxled_probe(struct platform_device *pdev) { int ret; - ret = led_classdev_register(&pdev->dev, &hp6xx_red_led); + ret = devm_led_classdev_register(&pdev->dev, &hp6xx_red_led); if (ret < 0) return ret; - ret = led_classdev_register(&pdev->dev, &hp6xx_green_led); - if (ret < 0) - led_classdev_unregister(&hp6xx_red_led); - - return ret; -} - -static int hp6xxled_remove(struct platform_device *pdev) -{ - led_classdev_unregister(&hp6xx_red_led); - led_classdev_unregister(&hp6xx_green_led); - - return 0; + return devm_led_classdev_register(&pdev->dev, &hp6xx_green_led); } static struct platform_driver hp6xxled_driver = { .probe = hp6xxled_probe, - .remove = hp6xxled_remove, .driver = { .name = "hp6xx-led", }, -- cgit v0.10.2 From 583a2b2cd73c13a91b5f529466dec4d27716d226 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Sat, 5 Sep 2015 19:53:27 +0530 Subject: leds: leds-ot200: Use devm_led_classdev_register Use resource-managed function devm_led_classdev_register instead of led_classdev_register to make the error path simpler. The goto is replaced with direct return, unneeded label err is dropped. Also, remove redundant ot200_led_remove. Signed-off-by: Muhammad Falak R Wani Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c index 39870de..12af112 100644 --- a/drivers/leds/leds-ot200.c +++ b/drivers/leds/leds-ot200.c @@ -124,9 +124,9 @@ static int ot200_led_probe(struct platform_device *pdev) leds[i].cdev.name = leds[i].name; leds[i].cdev.brightness_set = ot200_led_brightness_set; - ret = led_classdev_register(&pdev->dev, &leds[i].cdev); + ret = devm_led_classdev_register(&pdev->dev, &leds[i].cdev); if (ret < 0) - goto err; + return ret; } leds_front = 0; /* turn off all front leds */ @@ -135,27 +135,10 @@ static int ot200_led_probe(struct platform_device *pdev) outb(leds_back, 0x5a); return 0; - -err: - for (i = i - 1; i >= 0; i--) - led_classdev_unregister(&leds[i].cdev); - - return ret; -} - -static int ot200_led_remove(struct platform_device *pdev) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(leds); i++) - led_classdev_unregister(&leds[i].cdev); - - return 0; } static struct platform_driver ot200_led_driver = { .probe = ot200_led_probe, - .remove = ot200_led_remove, .driver = { .name = "leds-ot200", }, -- cgit v0.10.2 From 431557f4a44f582f83fd83cbee571baeab24b853 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Mon, 7 Sep 2015 19:43:23 +0530 Subject: leds: leds-ipaq-micro: Use devm_led_classdev_register Use of resource-managed function devm_led_classdev_register instead of led_classdev_register is preferred, consequently remove redundant function micro_leds_remove. Signed-off-by: Muhammad Falak R Wani Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-ipaq-micro.c b/drivers/leds/leds-ipaq-micro.c index 3776f51..1206215 100644 --- a/drivers/leds/leds-ipaq-micro.c +++ b/drivers/leds/leds-ipaq-micro.c @@ -111,7 +111,7 @@ static int micro_leds_probe(struct platform_device *pdev) { int ret; - ret = led_classdev_register(&pdev->dev, µ_led); + ret = devm_led_classdev_register(&pdev->dev, µ_led); if (ret) { dev_err(&pdev->dev, "registering led failed: %d\n", ret); return ret; @@ -121,18 +121,11 @@ static int micro_leds_probe(struct platform_device *pdev) return 0; } -static int micro_leds_remove(struct platform_device *pdev) -{ - led_classdev_unregister(µ_led); - return 0; -} - static struct platform_driver micro_leds_device_driver = { .driver = { .name = "ipaq-micro-leds", }, .probe = micro_leds_probe, - .remove = micro_leds_remove, }; module_platform_driver(micro_leds_device_driver); -- cgit v0.10.2 From 95281b5b598e9805b77dbbaaea400ebc2289bac8 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Mon, 7 Sep 2015 21:58:29 +0530 Subject: leds: leds-ipaq-micro: Fix coding style issues Spaces at the starting of a line are removed, indentation using tab, instead of space. Also, line width of more than 80 characters is also taken care of. Two warnings are left alone to aid better readability. Signed-off-by: Muhammad Falak R Wani Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-ipaq-micro.c b/drivers/leds/leds-ipaq-micro.c index 1206215..fa262b6 100644 --- a/drivers/leds/leds-ipaq-micro.c +++ b/drivers/leds/leds-ipaq-micro.c @@ -16,9 +16,9 @@ #define LED_YELLOW 0x00 #define LED_GREEN 0x01 -#define LED_EN (1 << 4) /* LED ON/OFF 0:off, 1:on */ -#define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */ -#define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */ +#define LED_EN (1 << 4) /* LED ON/OFF 0:off, 1:on */ +#define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */ +#define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */ static void micro_leds_brightness_set(struct led_classdev *led_cdev, enum led_brightness value) @@ -79,14 +79,14 @@ static int micro_leds_blink_set(struct led_classdev *led_cdev, }; msg.tx_data[0] = LED_GREEN; - if (*delay_on > IPAQ_LED_MAX_DUTY || + if (*delay_on > IPAQ_LED_MAX_DUTY || *delay_off > IPAQ_LED_MAX_DUTY) - return -EINVAL; + return -EINVAL; - if (*delay_on == 0 && *delay_off == 0) { - *delay_on = 100; - *delay_off = 100; - } + if (*delay_on == 0 && *delay_off == 0) { + *delay_on = 100; + *delay_off = 100; + } msg.tx_data[1] = 0; if (*delay_on >= IPAQ_LED_MAX_DUTY) -- cgit v0.10.2 From 22a16873d38829570677871a22cf77f00445206f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 3 Aug 2015 17:04:01 +0200 Subject: LED/MIPS: Move SEAD3 LED driver to where it belongs. Fixes the following randconfig problem leds-sead3.c:(.text+0x7dc): undefined reference to `led_classdev_unregister' leds-sead3.c:(.text+0x7e8): undefined reference to `led_classdev_unregister' Signed-off-by: Ralf Baechle Cc: Bryan Wu Cc: Richard Purdie Cc: Markos Chandras Cc: linux-leds@vger.kernel.org Cc: linux-mips@linux-mips.org Signed-off-by: Jacek Anaszewski diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile index 2e52cbd..7a584e0 100644 --- a/arch/mips/mti-sead3/Makefile +++ b/arch/mips/mti-sead3/Makefile @@ -12,6 +12,4 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ sead3-int.o sead3-platform.o sead3-reset.o \ sead3-setup.o sead3-time.o -obj-y += leds-sead3.o - obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o diff --git a/arch/mips/mti-sead3/leds-sead3.c b/arch/mips/mti-sead3/leds-sead3.c deleted file mode 100644 index c938cee..0000000 --- a/arch/mips/mti-sead3/leds-sead3.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. - * Copyright (C) 2015 Imagination Technologies, Inc. - */ -#include -#include -#include -#include -#include -#include -#include - -#include - -static void sead3_pled_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - writel(value, (void __iomem *)SEAD3_CPLD_P_LED); -} - -static void sead3_fled_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - writel(value, (void __iomem *)SEAD3_CPLD_F_LED); -} - -static struct led_classdev sead3_pled = { - .name = "sead3::pled", - .brightness_set = sead3_pled_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - -static struct led_classdev sead3_fled = { - .name = "sead3::fled", - .brightness_set = sead3_fled_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - -static int sead3_led_probe(struct platform_device *pdev) -{ - int ret; - - ret = led_classdev_register(&pdev->dev, &sead3_pled); - if (ret < 0) - return ret; - - ret = led_classdev_register(&pdev->dev, &sead3_fled); - if (ret < 0) - led_classdev_unregister(&sead3_pled); - - return ret; -} - -static int sead3_led_remove(struct platform_device *pdev) -{ - led_classdev_unregister(&sead3_pled); - led_classdev_unregister(&sead3_fled); - return 0; -} - -static struct platform_driver sead3_led_driver = { - .probe = sead3_led_probe, - .remove = sead3_led_remove, - .driver = { - .name = "sead3-led", - }, -}; - -module_platform_driver(sead3_led_driver); - -MODULE_AUTHOR("Kristian Kielhofner "); -MODULE_DESCRIPTION("SEAD3 LED driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 42990f2..b1ab8bd 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -556,6 +556,16 @@ config LEDS_KTD2692 Say Y to enable this driver. +config LEDS_SEAD3 + tristate "LED support for the MIPS SEAD 3 board" + depends on LEDS_CLASS && MIPS_SEAD3 + help + Say Y here to include support for the FLED and PLED LEDs on SEAD3 eval + boards. + + This driver can also be built as a module. If so the module + will be called leds-sead3. + comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)" config LEDS_BLINKM diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index b503f92..e9d53092 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o obj-$(CONFIG_LEDS_KTD2692) += leds-ktd2692.o obj-$(CONFIG_LEDS_POWERNV) += leds-powernv.o +obj-$(CONFIG_LEDS_SEAD3) += leds-sead3.o # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/drivers/leds/leds-sead3.c b/drivers/leds/leds-sead3.c new file mode 100644 index 0000000..eb97a32 --- /dev/null +++ b/drivers/leds/leds-sead3.c @@ -0,0 +1,78 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2015 Imagination Technologies, Inc. + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +static void sead3_pled_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + writel(value, (void __iomem *)SEAD3_CPLD_P_LED); +} + +static void sead3_fled_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + writel(value, (void __iomem *)SEAD3_CPLD_F_LED); +} + +static struct led_classdev sead3_pled = { + .name = "sead3::pled", + .brightness_set = sead3_pled_set, + .flags = LED_CORE_SUSPENDRESUME, +}; + +static struct led_classdev sead3_fled = { + .name = "sead3::fled", + .brightness_set = sead3_fled_set, + .flags = LED_CORE_SUSPENDRESUME, +}; + +static int sead3_led_probe(struct platform_device *pdev) +{ + int ret; + + ret = led_classdev_register(&pdev->dev, &sead3_pled); + if (ret < 0) + return ret; + + ret = led_classdev_register(&pdev->dev, &sead3_fled); + if (ret < 0) + led_classdev_unregister(&sead3_pled); + + return ret; +} + +static int sead3_led_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&sead3_pled); + led_classdev_unregister(&sead3_fled); + + return 0; +} + +static struct platform_driver sead3_led_driver = { + .probe = sead3_led_probe, + .remove = sead3_led_remove, + .driver = { + .name = "sead3-led", + }, +}; + +module_platform_driver(sead3_led_driver); + +MODULE_AUTHOR("Kristian Kielhofner "); +MODULE_DESCRIPTION("SEAD3 LED driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 757b06ae04b3b6c8958ab067e879a8865d076d2a Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Mon, 28 Sep 2015 14:38:04 +0200 Subject: leds: core: Move LED core callbacks out of led-class.c Since the API for controlling LED brightness and blinking is defined in the LED core, move the related timer and work callbacks to the led-core.c, and initialize them through a new led_core_init API. Signed-off-by: Jacek Anaszewski Acked-by: Andrew Lunn Acked-by: Pavel Machek diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index ca51d58..7385f98 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -102,70 +102,6 @@ static const struct attribute_group *led_groups[] = { NULL, }; -static void led_timer_function(unsigned long data) -{ - struct led_classdev *led_cdev = (void *)data; - unsigned long brightness; - unsigned long delay; - - if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) { - led_set_brightness_async(led_cdev, LED_OFF); - return; - } - - if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) { - led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; - return; - } - - brightness = led_get_brightness(led_cdev); - if (!brightness) { - /* Time to switch the LED on. */ - if (led_cdev->delayed_set_value) { - led_cdev->blink_brightness = - led_cdev->delayed_set_value; - led_cdev->delayed_set_value = 0; - } - brightness = led_cdev->blink_brightness; - delay = led_cdev->blink_delay_on; - } else { - /* Store the current brightness value to be able - * to restore it when the delay_off period is over. - */ - led_cdev->blink_brightness = brightness; - brightness = LED_OFF; - delay = led_cdev->blink_delay_off; - } - - led_set_brightness_async(led_cdev, brightness); - - /* Return in next iteration if led is in one-shot mode and we are in - * the final blink state so that the led is toggled each delay_on + - * delay_off milliseconds in worst case. - */ - if (led_cdev->flags & LED_BLINK_ONESHOT) { - if (led_cdev->flags & LED_BLINK_INVERT) { - if (brightness) - led_cdev->flags |= LED_BLINK_ONESHOT_STOP; - } else { - if (!brightness) - led_cdev->flags |= LED_BLINK_ONESHOT_STOP; - } - } - - mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); -} - -static void set_brightness_delayed(struct work_struct *ws) -{ - struct led_classdev *led_cdev = - container_of(ws, struct led_classdev, set_brightness_work); - - led_stop_software_blink(led_cdev); - - led_set_brightness_async(led_cdev, led_cdev->delayed_set_value); -} - /** * led_classdev_suspend - suspend an led_classdev. * @led_cdev: the led_classdev to suspend. @@ -283,10 +219,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) led_update_brightness(led_cdev); - INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed); - - setup_timer(&led_cdev->blink_timer, led_timer_function, - (unsigned long)led_cdev); + led_init_core(led_cdev); #ifdef CONFIG_LEDS_TRIGGERS led_trigger_set_default(led_cdev); diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index 549de7e..c1c3af0 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -25,6 +25,70 @@ EXPORT_SYMBOL_GPL(leds_list_lock); LIST_HEAD(leds_list); EXPORT_SYMBOL_GPL(leds_list); +static void led_timer_function(unsigned long data) +{ + struct led_classdev *led_cdev = (void *)data; + unsigned long brightness; + unsigned long delay; + + if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) { + led_set_brightness_async(led_cdev, LED_OFF); + return; + } + + if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) { + led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; + return; + } + + brightness = led_get_brightness(led_cdev); + if (!brightness) { + /* Time to switch the LED on. */ + if (led_cdev->delayed_set_value) { + led_cdev->blink_brightness = + led_cdev->delayed_set_value; + led_cdev->delayed_set_value = 0; + } + brightness = led_cdev->blink_brightness; + delay = led_cdev->blink_delay_on; + } else { + /* Store the current brightness value to be able + * to restore it when the delay_off period is over. + */ + led_cdev->blink_brightness = brightness; + brightness = LED_OFF; + delay = led_cdev->blink_delay_off; + } + + led_set_brightness_async(led_cdev, brightness); + + /* Return in next iteration if led is in one-shot mode and we are in + * the final blink state so that the led is toggled each delay_on + + * delay_off milliseconds in worst case. + */ + if (led_cdev->flags & LED_BLINK_ONESHOT) { + if (led_cdev->flags & LED_BLINK_INVERT) { + if (brightness) + led_cdev->flags |= LED_BLINK_ONESHOT_STOP; + } else { + if (!brightness) + led_cdev->flags |= LED_BLINK_ONESHOT_STOP; + } + } + + mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); +} + +static void set_brightness_delayed(struct work_struct *ws) +{ + struct led_classdev *led_cdev = + container_of(ws, struct led_classdev, set_brightness_work); + + led_stop_software_blink(led_cdev); + + led_set_brightness_async(led_cdev, led_cdev->delayed_set_value); +} + static void led_set_software_blink(struct led_classdev *led_cdev, unsigned long delay_on, unsigned long delay_off) @@ -72,6 +136,15 @@ static void led_blink_setup(struct led_classdev *led_cdev, led_set_software_blink(led_cdev, *delay_on, *delay_off); } +void led_init_core(struct led_classdev *led_cdev) +{ + INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed); + + setup_timer(&led_cdev->blink_timer, led_timer_function, + (unsigned long)led_cdev); +} +EXPORT_SYMBOL_GPL(led_init_core); + void led_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index bc89d7a..4238fbc 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -44,6 +44,7 @@ static inline int led_get_brightness(struct led_classdev *led_cdev) return led_cdev->brightness; } +void led_init_core(struct led_classdev *led_cdev); void led_stop_software_blink(struct led_classdev *led_cdev); extern struct rw_semaphore leds_list_lock; -- cgit v0.10.2 From 1c7b9d0edf5ada916fd02e66355f79f2089ee095 Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Thu, 8 Oct 2015 10:32:26 +0200 Subject: leds: triggers: add invert to heartbeat This patch adds possibility to invert heartbeat blinking. The inverted LED is more time ON then OFF. It's because it looks better when the heartbeat LED is next to other LED which is most time ON. The invert value is exported same way via sysfs in file invert like oneshot. I get inspiration from this trigger. Signed-off-by: Jiri Prchal Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c index fea6871..8622ce6 100644 --- a/drivers/leds/trigger/ledtrig-heartbeat.c +++ b/drivers/leds/trigger/ledtrig-heartbeat.c @@ -27,6 +27,7 @@ struct heartbeat_trig_data { unsigned int phase; unsigned int period; struct timer_list timer; + unsigned int invert; }; static void led_heartbeat_function(unsigned long data) @@ -56,21 +57,27 @@ static void led_heartbeat_function(unsigned long data) msecs_to_jiffies(heartbeat_data->period); delay = msecs_to_jiffies(70); heartbeat_data->phase++; - brightness = led_cdev->max_brightness; + if (!heartbeat_data->invert) + brightness = led_cdev->max_brightness; break; case 1: delay = heartbeat_data->period / 4 - msecs_to_jiffies(70); heartbeat_data->phase++; + if (heartbeat_data->invert) + brightness = led_cdev->max_brightness; break; case 2: delay = msecs_to_jiffies(70); heartbeat_data->phase++; - brightness = led_cdev->max_brightness; + if (!heartbeat_data->invert) + brightness = led_cdev->max_brightness; break; default: delay = heartbeat_data->period - heartbeat_data->period / 4 - msecs_to_jiffies(70); heartbeat_data->phase = 0; + if (heartbeat_data->invert) + brightness = led_cdev->max_brightness; break; } @@ -78,15 +85,50 @@ static void led_heartbeat_function(unsigned long data) mod_timer(&heartbeat_data->timer, jiffies + delay); } +static ssize_t led_invert_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + + return sprintf(buf, "%u\n", heartbeat_data->invert); +} + +static ssize_t led_invert_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + unsigned long state; + int ret; + + ret = kstrtoul(buf, 0, &state); + if (ret) + return ret; + + heartbeat_data->invert = !!state; + + return size; +} + +static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); + static void heartbeat_trig_activate(struct led_classdev *led_cdev) { struct heartbeat_trig_data *heartbeat_data; + int rc; heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); if (!heartbeat_data) return; led_cdev->trigger_data = heartbeat_data; + rc = device_create_file(led_cdev->dev, &dev_attr_invert); + if (rc) { + kfree(led_cdev->trigger_data); + return; + } + setup_timer(&heartbeat_data->timer, led_heartbeat_function, (unsigned long) led_cdev); heartbeat_data->phase = 0; @@ -100,6 +142,7 @@ static void heartbeat_trig_deactivate(struct led_classdev *led_cdev) if (led_cdev->activated) { del_timer_sync(&heartbeat_data->timer); + device_remove_file(led_cdev->dev, &dev_attr_invert); kfree(heartbeat_data); led_cdev->activated = false; } -- cgit v0.10.2 From 2976b17989094e97567510be3ea91fc2f0c7aab3 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Sat, 26 Sep 2015 23:02:34 +0200 Subject: leds: netxbig: add device tree binding This patch adds device tree support for the netxbig LEDs. This also introduces a additionnal DT binding for the GPIO extension bus (netxbig-gpio-ext) used to configure the LEDs. Since this bus could also be used to control other devices, then it seems more suitable to have it in a separate DT binding. Signed-off-by: Simon Guinot Acked-by: Linus Walleij Signed-off-by: Jacek Anaszewski diff --git a/Documentation/devicetree/bindings/gpio/netxbig-gpio-ext.txt b/Documentation/devicetree/bindings/gpio/netxbig-gpio-ext.txt new file mode 100644 index 0000000..50ec2e6 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/netxbig-gpio-ext.txt @@ -0,0 +1,22 @@ +Binding for the GPIO extension bus found on some LaCie/Seagate boards +(Example: 2Big/5Big Network v2, 2Big NAS). + +Required properties: +- compatible: "lacie,netxbig-gpio-ext". +- addr-gpios: GPIOs representing the address register (LSB -> MSB). +- data-gpios: GPIOs representing the data register (LSB -> MSB). +- enable-gpio: latches the new configuration (address, data) on raising edge. + +Example: + +netxbig_gpio_ext: netxbig-gpio-ext { + compatible = "lacie,netxbig-gpio-ext"; + + addr-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH + &gpio1 16 GPIO_ACTIVE_HIGH + &gpio1 17 GPIO_ACTIVE_HIGH>; + data-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH + &gpio1 13 GPIO_ACTIVE_HIGH + &gpio1 14 GPIO_ACTIVE_HIGH>; + enable-gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>; +}; diff --git a/Documentation/devicetree/bindings/leds/leds-netxbig.txt b/Documentation/devicetree/bindings/leds/leds-netxbig.txt new file mode 100644 index 0000000..5ef92a2 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-netxbig.txt @@ -0,0 +1,92 @@ +Binding for the CPLD LEDs (GPIO extension bus) found on some LaCie/Seagate +boards (Example: 2Big/5Big Network v2, 2Big NAS). + +Required properties: +- compatible: "lacie,netxbig-leds". +- gpio-ext: Phandle for the gpio-ext bus. + +Optional properties: +- timers: Timer array. Each timer entry is represented by three integers: + Mode (gpio-ext bus), delay_on and delay_off. + +Each LED is represented as a sub-node of the netxbig-leds device. + +Required sub-node properties: +- mode-addr: Mode register address on gpio-ext bus. +- mode-val: Mode to value mapping. Each entry is represented by two integers: + A mode and the corresponding value on the gpio-ext bus. +- bright-addr: Brightness register address on gpio-ext bus. +- max-brightness: Maximum brightness value. + +Optional sub-node properties: +- label: Name for this LED. If omitted, the label is taken from the node name. +- linux,default-trigger: Trigger assigned to the LED. + +Example: + +netxbig-leds { + compatible = "lacie,netxbig-leds"; + + gpio-ext = &gpio_ext; + + timers = ; + + blue-power { + label = "netxbig:blue:power"; + mode-addr = <0>; + mode-val = ; + bright-addr = <1>; + max-brightness = <7>; + }; + red-power { + label = "netxbig:red:power"; + mode-addr = <0>; + mode-val = ; + bright-addr = <1>; + max-brightness = <7>; + }; + blue-sata0 { + label = "netxbig:blue:sata0"; + mode-addr = <3>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + red-sata0 { + label = "netxbig:red:sata0"; + mode-addr = <3>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + blue-sata1 { + label = "netxbig:blue:sata1"; + mode-addr = <4>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + red-sata1 { + label = "netxbig:red:sata1"; + mode-addr = <4>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; +}; diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index 25e4197..e1f3c26 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -140,6 +141,11 @@ struct netxbig_led_data { spinlock_t lock; }; +struct netxbig_led_priv { + struct netxbig_led_platform_data *pdata; + struct netxbig_led_data leds_data[]; +}; + static int netxbig_led_get_timer_mode(enum netxbig_led_mode *mode, unsigned long delay_on, unsigned long delay_off, @@ -304,12 +310,12 @@ static void delete_netxbig_led(struct netxbig_led_data *led_dat) led_classdev_unregister(&led_dat->cdev); } -static int -create_netxbig_led(struct platform_device *pdev, - struct netxbig_led_data *led_dat, - const struct netxbig_led *template) +static int create_netxbig_led(struct platform_device *pdev, int led, + struct netxbig_led_priv *priv) { - struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct netxbig_led_platform_data *pdata = priv->pdata; + struct netxbig_led_data *led_dat = &priv->leds_data[led]; + const struct netxbig_led *template = &priv->pdata->leds[led]; spin_lock_init(&led_dat->lock); led_dat->gpio_ext = pdata->gpio_ext; @@ -333,7 +339,7 @@ create_netxbig_led(struct platform_device *pdev, led_dat->mode_addr = template->mode_addr; led_dat->mode_val = template->mode_val; led_dat->bright_addr = template->bright_addr; - led_dat->bright_max = (1 << pdata->gpio_ext->num_data) - 1; + led_dat->bright_max = template->bright_max; led_dat->timer = pdata->timer; led_dat->num_timer = pdata->num_timer; /* @@ -346,38 +352,269 @@ create_netxbig_led(struct platform_device *pdev, return 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) +{ + int *addr, *data; + int num_addr, num_data; + int ret; + int i; + + ret = of_gpio_named_count(np, "addr-gpios"); + if (ret < 0) { + dev_err(dev, + "Failed to count GPIOs in DT property addr-gpios\n"); + return ret; + } + num_addr = ret; + addr = devm_kzalloc(dev, num_addr * sizeof(*addr), GFP_KERNEL); + if (!addr) + return -ENOMEM; + + for (i = 0; i < num_addr; i++) { + ret = of_get_named_gpio(np, "addr-gpios", i); + if (ret < 0) + return ret; + addr[i] = ret; + } + gpio_ext->addr = addr; + gpio_ext->num_addr = num_addr; + + ret = of_gpio_named_count(np, "data-gpios"); + if (ret < 0) { + dev_err(dev, + "Failed to count GPIOs in DT property data-gpios\n"); + return ret; + } + num_data = ret; + data = devm_kzalloc(dev, num_data * sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + for (i = 0; i < num_data; i++) { + ret = of_get_named_gpio(np, "data-gpios", i); + if (ret < 0) + return ret; + data[i] = ret; + } + gpio_ext->data = data; + gpio_ext->num_data = num_data; + + ret = of_get_named_gpio(np, "enable-gpio", 0); + if (ret < 0) { + dev_err(dev, + "Failed to get GPIO from DT property enable-gpio\n"); + return ret; + } + gpio_ext->enable = ret; + + return 0; +} + +static int netxbig_leds_get_of_pdata(struct device *dev, + struct netxbig_led_platform_data *pdata) +{ + struct device_node *np = dev->of_node; + struct device_node *gpio_ext_np; + struct device_node *child; + struct netxbig_gpio_ext *gpio_ext; + struct netxbig_led_timer *timers; + struct netxbig_led *leds, *led; + int num_timers; + int num_leds = 0; + int ret; + int i; + + /* GPIO extension */ + gpio_ext_np = of_parse_phandle(np, "gpio-ext", 0); + if (!gpio_ext_np) { + dev_err(dev, "Failed to get DT handle gpio-ext\n"); + return -EINVAL; + } + + gpio_ext = devm_kzalloc(dev, sizeof(*gpio_ext), GFP_KERNEL); + if (!gpio_ext) + return -ENOMEM; + ret = gpio_ext_get_of_pdata(dev, gpio_ext_np, gpio_ext); + if (ret) + return ret; + of_node_put(gpio_ext_np); + pdata->gpio_ext = gpio_ext; + + /* Timers (optional) */ + ret = of_property_count_u32_elems(np, "timers"); + if (ret > 0) { + if (ret % 3) + return -EINVAL; + num_timers = ret / 3; + timers = devm_kzalloc(dev, num_timers * sizeof(*timers), + GFP_KERNEL); + if (!timers) + return -ENOMEM; + for (i = 0; i < num_timers; i++) { + u32 tmp; + + of_property_read_u32_index(np, "timers", 3 * i, + &timers[i].mode); + if (timers[i].mode >= NETXBIG_LED_MODE_NUM) + return -EINVAL; + of_property_read_u32_index(np, "timers", + 3 * i + 1, &tmp); + timers[i].delay_on = tmp; + of_property_read_u32_index(np, "timers", + 3 * i + 2, &tmp); + timers[i].delay_off = tmp; + } + pdata->timer = timers; + pdata->num_timer = num_timers; + } + + /* LEDs */ + num_leds = of_get_child_count(np); + if (!num_leds) { + dev_err(dev, "No LED subnodes found in DT\n"); + return -ENODEV; + } + + leds = devm_kzalloc(dev, num_leds * sizeof(*leds), GFP_KERNEL); + if (!leds) + return -ENOMEM; + + led = leds; + for_each_child_of_node(np, child) { + const char *string; + int *mode_val; + int num_modes; + + ret = of_property_read_u32(child, "mode-addr", + &led->mode_addr); + if (ret) + goto err_node_put; + + ret = of_property_read_u32(child, "bright-addr", + &led->bright_addr); + if (ret) + goto err_node_put; + + ret = of_property_read_u32(child, "max-brightness", + &led->bright_max); + if (ret) + goto err_node_put; + + mode_val = + devm_kzalloc(dev, + NETXBIG_LED_MODE_NUM * sizeof(*mode_val), + GFP_KERNEL); + if (!mode_val) { + ret = -ENOMEM; + goto err_node_put; + } + + for (i = 0; i < NETXBIG_LED_MODE_NUM; i++) + mode_val[i] = NETXBIG_LED_INVALID_MODE; + + ret = of_property_count_u32_elems(child, "mode-val"); + if (ret < 0 || ret % 2) { + ret = -EINVAL; + goto err_node_put; + } + num_modes = ret / 2; + if (num_modes > NETXBIG_LED_MODE_NUM) { + ret = -EINVAL; + goto err_node_put; + } + + for (i = 0; i < num_modes; i++) { + int mode; + int val; + + of_property_read_u32_index(child, + "mode-val", 2 * i, &mode); + of_property_read_u32_index(child, + "mode-val", 2 * i + 1, &val); + if (mode >= NETXBIG_LED_MODE_NUM) { + ret = -EINVAL; + goto err_node_put; + } + mode_val[mode] = val; + } + led->mode_val = mode_val; + + if (!of_property_read_string(child, "label", &string)) + led->name = string; + else + led->name = child->name; + + if (!of_property_read_string(child, + "linux,default-trigger", &string)) + led->default_trigger = string; + + led++; + } + + pdata->leds = leds; + pdata->num_leds = num_leds; + + return 0; + +err_node_put: + of_node_put(child); + return ret; +} + +static const struct of_device_id of_netxbig_leds_match[] = { + { .compatible = "lacie,netxbig-leds", }, + {}, +}; +#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_data *leds_data; + struct netxbig_led_priv *priv; int i; int ret; - if (!pdata) - return -EINVAL; + 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; + } - leds_data = devm_kzalloc(&pdev->dev, - sizeof(struct netxbig_led_data) * pdata->num_leds, GFP_KERNEL); - if (!leds_data) + priv = devm_kzalloc(&pdev->dev, sizeof(*priv) + + pdata->num_leds * sizeof(struct netxbig_led_data), + GFP_KERNEL); + if (!priv) return -ENOMEM; + priv->pdata = pdata; ret = gpio_ext_init(pdata->gpio_ext); if (ret < 0) return ret; for (i = 0; i < pdata->num_leds; i++) { - ret = create_netxbig_led(pdev, &leds_data[i], &pdata->leds[i]); + ret = create_netxbig_led(pdev, i, priv); if (ret < 0) goto err_free_leds; } - - platform_set_drvdata(pdev, leds_data); + platform_set_drvdata(pdev, priv); return 0; err_free_leds: for (i = i - 1; i >= 0; i--) - delete_netxbig_led(&leds_data[i]); + delete_netxbig_led(&priv->leds_data[i]); gpio_ext_free(pdata->gpio_ext); return ret; @@ -385,14 +622,12 @@ err_free_leds: static int netxbig_led_remove(struct platform_device *pdev) { - struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct netxbig_led_data *leds_data; + struct netxbig_led_priv *priv = platform_get_drvdata(pdev); + struct netxbig_led_platform_data *pdata = priv->pdata; int i; - leds_data = platform_get_drvdata(pdev); - for (i = 0; i < pdata->num_leds; i++) - delete_netxbig_led(&leds_data[i]); + delete_netxbig_led(&priv->leds_data[i]); gpio_ext_free(pdata->gpio_ext); @@ -403,7 +638,8 @@ static struct platform_driver netxbig_led_driver = { .probe = netxbig_led_probe, .remove = netxbig_led_remove, .driver = { - .name = "leds-netxbig", + .name = "leds-netxbig", + .of_match_table = of_match_ptr(of_netxbig_leds_match), }, }; diff --git a/include/dt-bindings/leds/leds-netxbig.h b/include/dt-bindings/leds/leds-netxbig.h new file mode 100644 index 0000000..92658b0 --- /dev/null +++ b/include/dt-bindings/leds/leds-netxbig.h @@ -0,0 +1,18 @@ +/* + * This header provides constants for netxbig LED bindings. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef _DT_BINDINGS_LEDS_NETXBIG_H +#define _DT_BINDINGS_LEDS_NETXBIG_H + +#define NETXBIG_LED_OFF 0 +#define NETXBIG_LED_ON 1 +#define NETXBIG_LED_SATA 2 +#define NETXBIG_LED_TIMER1 3 +#define NETXBIG_LED_TIMER2 4 + +#endif /* _DT_BINDINGS_LEDS_NETXBIG_H */ diff --git a/include/linux/platform_data/leds-kirkwood-netxbig.h b/include/linux/platform_data/leds-kirkwood-netxbig.h index d2be19a..3c85a73 100644 --- a/include/linux/platform_data/leds-kirkwood-netxbig.h +++ b/include/linux/platform_data/leds-kirkwood-netxbig.h @@ -40,6 +40,7 @@ struct netxbig_led { int mode_addr; int *mode_val; int bright_addr; + int bright_max; }; struct netxbig_led_platform_data { -- cgit v0.10.2 From 767361fac0f730293c1be8cdf1636cf9510b2245 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Sat, 26 Sep 2015 23:02:35 +0200 Subject: ARM: Kirkwood: add LED DT entries for netxbig boards This patch adds DT entries for the LEDs found on the Kirkwood-based LaCie boards 2Big and 5Big Network v2. Signed-off-by: Simon Guinot Acked-by: Gregory CLEMENT Signed-off-by: Jacek Anaszewski diff --git a/arch/arm/boot/dts/kirkwood-net5big.dts b/arch/arm/boot/dts/kirkwood-net5big.dts index 36155b7..d2d44df 100644 --- a/arch/arm/boot/dts/kirkwood-net5big.dts +++ b/arch/arm/boot/dts/kirkwood-net5big.dts @@ -86,6 +86,66 @@ clock-frequency = <32768>; }; }; + + netxbig-leds { + blue-sata2 { + label = "netxbig:blue:sata2"; + mode-addr = <5>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + red-sata2 { + label = "netxbig:red:sata2"; + mode-addr = <5>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + blue-sata3 { + label = "netxbig:blue:sata3"; + mode-addr = <6>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + red-sata3 { + label = "netxbig:red:sata3"; + mode-addr = <6>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + blue-sata4 { + label = "netxbig:blue:sata4"; + mode-addr = <7>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + red-sata4 { + label = "netxbig:red:sata4"; + mode-addr = <7>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + }; }; &mdio { diff --git a/arch/arm/boot/dts/kirkwood-netxbig.dtsi b/arch/arm/boot/dts/kirkwood-netxbig.dtsi index 1508b121..62515a8 100644 --- a/arch/arm/boot/dts/kirkwood-netxbig.dtsi +++ b/arch/arm/boot/dts/kirkwood-netxbig.dtsi @@ -13,6 +13,7 @@ * warranty of any kind, whether express or implied. */ +#include #include "kirkwood.dtsi" #include "kirkwood-6281.dtsi" @@ -105,6 +106,85 @@ gpio = <&gpio0 16 GPIO_ACTIVE_HIGH>; }; }; + + netxbig_gpio_ext: netxbig-gpio-ext { + compatible = "lacie,netxbig-gpio-ext"; + + addr-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH + &gpio1 16 GPIO_ACTIVE_HIGH + &gpio1 17 GPIO_ACTIVE_HIGH>; + data-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH + &gpio1 13 GPIO_ACTIVE_HIGH + &gpio1 14 GPIO_ACTIVE_HIGH>; + enable-gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>; + }; + + netxbig-leds { + compatible = "lacie,netxbig-leds"; + + gpio-ext = <&netxbig_gpio_ext>; + + timers = ; + + blue-power { + label = "netxbig:blue:power"; + mode-addr = <0>; + mode-val = ; + bright-addr = <1>; + max-brightness = <7>; + }; + red-power { + label = "netxbig:red:power"; + mode-addr = <0>; + mode-val = ; + bright-addr = <1>; + max-brightness = <7>; + }; + blue-sata0 { + label = "netxbig:blue:sata0"; + mode-addr = <3>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + red-sata0 { + label = "netxbig:red:sata0"; + mode-addr = <3>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + blue-sata1 { + label = "netxbig:blue:sata1"; + mode-addr = <4>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + red-sata1 { + label = "netxbig:red:sata1"; + mode-addr = <4>; + mode-val = ; + bright-addr = <2>; + max-brightness = <7>; + }; + }; }; &mdio { -- cgit v0.10.2 From ebc278f1575942d08ad3278b71cde99bd24eae63 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Sat, 26 Sep 2015 23:02:36 +0200 Subject: ARM: mvebu: remove static LED setup for netxbig boards Since DT support is now available for the LEDs found on the LaCie netxbig boards (Kirkwood-based), then the old-fashion netxbig board setup file is no longer needed. This patch removes this file. Signed-off-by: Simon Guinot Acked-by: Gregory CLEMENT Signed-off-by: Jacek Anaszewski diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index c86a5a0..e20fc41 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -117,11 +117,4 @@ config MACH_KIRKWOOD Say 'Y' here if you want your kernel to support boards based on the Marvell Kirkwood device tree. -config MACH_NETXBIG - bool "LaCie 2Big and 5Big Network v2" - depends on MACH_KIRKWOOD - help - Say 'Y' here if you want your kernel to support the - LaCie 2Big and 5Big Network v2 - endif diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index b4f0149..ecf9e0c 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -13,4 +13,3 @@ endif obj-$(CONFIG_MACH_DOVE) += dove.o obj-$(CONFIG_MACH_KIRKWOOD) += kirkwood.o kirkwood-pm.o -obj-$(CONFIG_MACH_NETXBIG) += netxbig.o diff --git a/arch/arm/mach-mvebu/board.h b/arch/arm/mach-mvebu/board.h deleted file mode 100644 index 98e32cc..0000000 --- a/arch/arm/mach-mvebu/board.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Board functions for Marvell System On Chip - * - * Copyright (C) 2014 - * - * Andrew Lunn - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#ifndef __ARCH_MVEBU_BOARD_H -#define __ARCH_MVEBU_BOARD_H - -#ifdef CONFIG_MACH_NETXBIG -void netxbig_init(void); -#else -static inline void netxbig_init(void) {}; -#endif -#endif diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c index 925f75f..f9d8e1e 100644 --- a/arch/arm/mach-mvebu/kirkwood.c +++ b/arch/arm/mach-mvebu/kirkwood.c @@ -25,7 +25,6 @@ #include "kirkwood.h" #include "kirkwood-pm.h" #include "common.h" -#include "board.h" static struct resource kirkwood_cpufreq_resources[] = { [0] = { @@ -180,9 +179,6 @@ static void __init kirkwood_dt_init(void) kirkwood_pm_init(); kirkwood_dt_eth_fixup(); - if (of_machine_is_compatible("lacie,netxbig")) - netxbig_init(); - of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL); } diff --git a/arch/arm/mach-mvebu/netxbig.c b/arch/arm/mach-mvebu/netxbig.c deleted file mode 100644 index 94b11b6..0000000 --- a/arch/arm/mach-mvebu/netxbig.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * arch/arm/mach-mvbu/board-netxbig.c - * - * LaCie 2Big and 5Big Network v2 board setup - * - * Copyright (C) 2010 Simon Guinot - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include "common.h" - -/***************************************************************************** - * GPIO extension LEDs - ****************************************************************************/ - -/* - * The LEDs are controlled by a CPLD and can be configured through a GPIO - * extension bus: - * - * - address register : bit [0-2] -> GPIO [47-49] - * - data register : bit [0-2] -> GPIO [44-46] - * - enable register : GPIO 29 - */ - -static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 }; -static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 }; - -static struct netxbig_gpio_ext netxbig_v2_gpio_ext = { - .addr = netxbig_v2_gpio_ext_addr, - .num_addr = ARRAY_SIZE(netxbig_v2_gpio_ext_addr), - .data = netxbig_v2_gpio_ext_data, - .num_data = ARRAY_SIZE(netxbig_v2_gpio_ext_data), - .enable = 29, -}; - -/* - * Address register selection: - * - * addr | register - * ---------------------------- - * 0 | front LED - * 1 | front LED brightness - * 2 | SATA LED brightness - * 3 | SATA0 LED - * 4 | SATA1 LED - * 5 | SATA2 LED - * 6 | SATA3 LED - * 7 | SATA4 LED - * - * Data register configuration: - * - * data | LED brightness - * ------------------------------------------------- - * 0 | min (off) - * - | - - * 7 | max - * - * data | front LED mode - * ------------------------------------------------- - * 0 | fix off - * 1 | fix blue on - * 2 | fix red on - * 3 | blink blue on=1 sec and blue off=1 sec - * 4 | blink red on=1 sec and red off=1 sec - * 5 | blink blue on=2.5 sec and red on=0.5 sec - * 6 | blink blue on=1 sec and red on=1 sec - * 7 | blink blue on=0.5 sec and blue off=2.5 sec - * - * data | SATA LED mode - * ------------------------------------------------- - * 0 | fix off - * 1 | SATA activity blink - * 2 | fix red on - * 3 | blink blue on=1 sec and blue off=1 sec - * 4 | blink red on=1 sec and red off=1 sec - * 5 | blink blue on=2.5 sec and red on=0.5 sec - * 6 | blink blue on=1 sec and red on=1 sec - * 7 | fix blue on - */ - -static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = { - [NETXBIG_LED_OFF] = 0, - [NETXBIG_LED_ON] = 2, - [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE, - [NETXBIG_LED_TIMER1] = 4, - [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE, -}; - -static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = { - [NETXBIG_LED_OFF] = 0, - [NETXBIG_LED_ON] = 1, - [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE, - [NETXBIG_LED_TIMER1] = 3, - [NETXBIG_LED_TIMER2] = 7, -}; - -static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = { - [NETXBIG_LED_OFF] = 0, - [NETXBIG_LED_ON] = 7, - [NETXBIG_LED_SATA] = 1, - [NETXBIG_LED_TIMER1] = 3, - [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE, -}; - -static struct netxbig_led_timer netxbig_v2_led_timer[] = { - [0] = { - .delay_on = 500, - .delay_off = 500, - .mode = NETXBIG_LED_TIMER1, - }, - [1] = { - .delay_on = 500, - .delay_off = 1000, - .mode = NETXBIG_LED_TIMER2, - }, -}; - -#define NETXBIG_LED(_name, maddr, mval, baddr) \ - { .name = _name, \ - .mode_addr = maddr, \ - .mode_val = mval, \ - .bright_addr = baddr } - -static struct netxbig_led net2big_v2_leds_ctrl[] = { - NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1), - NETXBIG_LED("net2big-v2:red:power", 0, netxbig_v2_red_mled, 1), - NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2), - NETXBIG_LED("net2big-v2:red:sata0", 3, netxbig_v2_red_mled, 2), - NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2), - NETXBIG_LED("net2big-v2:red:sata1", 4, netxbig_v2_red_mled, 2), -}; - -static struct netxbig_led_platform_data net2big_v2_leds_data = { - .gpio_ext = &netxbig_v2_gpio_ext, - .timer = netxbig_v2_led_timer, - .num_timer = ARRAY_SIZE(netxbig_v2_led_timer), - .leds = net2big_v2_leds_ctrl, - .num_leds = ARRAY_SIZE(net2big_v2_leds_ctrl), -}; - -static struct netxbig_led net5big_v2_leds_ctrl[] = { - NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1), - NETXBIG_LED("net5big-v2:red:power", 0, netxbig_v2_red_mled, 1), - NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2), - NETXBIG_LED("net5big-v2:red:sata0", 3, netxbig_v2_red_mled, 2), - NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2), - NETXBIG_LED("net5big-v2:red:sata1", 4, netxbig_v2_red_mled, 2), - NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2), - NETXBIG_LED("net5big-v2:red:sata2", 5, netxbig_v2_red_mled, 2), - NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2), - NETXBIG_LED("net5big-v2:red:sata3", 6, netxbig_v2_red_mled, 2), - NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2), - NETXBIG_LED("net5big-v2:red:sata4", 7, netxbig_v2_red_mled, 2), -}; - -static struct netxbig_led_platform_data net5big_v2_leds_data = { - .gpio_ext = &netxbig_v2_gpio_ext, - .timer = netxbig_v2_led_timer, - .num_timer = ARRAY_SIZE(netxbig_v2_led_timer), - .leds = net5big_v2_leds_ctrl, - .num_leds = ARRAY_SIZE(net5big_v2_leds_ctrl), -}; - -static struct platform_device netxbig_v2_leds = { - .name = "leds-netxbig", - .id = -1, - .dev = { - .platform_data = &net2big_v2_leds_data, - }, -}; - -void __init netxbig_init(void) -{ - - if (of_machine_is_compatible("lacie,net5big_v2")) - netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data; - platform_device_register(&netxbig_v2_leds); -} -- cgit v0.10.2 From cd0109555bd118ddb8ee0df0ca5d8f9bd3d7a77f Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Sat, 26 Sep 2015 23:02:37 +0200 Subject: leds: netxbig: convert to use the devm_ functions This patch converts the leds-netxbig driver to use the devres functions devm_gpio_request_one() and devm_led_classdev_register(). This allows to simplify the code a bit. Signed-off-by: Simon Guinot Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index e1f3c26..b166fd9 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c @@ -71,7 +71,8 @@ static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext, spin_unlock_irqrestore(&gpio_ext_lock, flags); } -static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext) +static int gpio_ext_init(struct platform_device *pdev, + struct netxbig_gpio_ext *gpio_ext) { int err; int i; @@ -81,46 +82,28 @@ static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext) /* Configure address GPIOs. */ for (i = 0; i < gpio_ext->num_addr; i++) { - err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW, - "GPIO extension addr"); + err = devm_gpio_request_one(&pdev->dev, gpio_ext->addr[i], + GPIOF_OUT_INIT_LOW, + "GPIO extension addr"); if (err) - goto err_free_addr; + return err; } /* Configure data GPIOs. */ for (i = 0; i < gpio_ext->num_data; i++) { - err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW, - "GPIO extension data"); + err = devm_gpio_request_one(&pdev->dev, gpio_ext->data[i], + GPIOF_OUT_INIT_LOW, + "GPIO extension data"); if (err) - goto err_free_data; + return err; } /* Configure "enable select" GPIO. */ - err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW, - "GPIO extension enable"); + err = devm_gpio_request_one(&pdev->dev, gpio_ext->enable, + GPIOF_OUT_INIT_LOW, + "GPIO extension enable"); if (err) - goto err_free_data; + return err; return 0; - -err_free_data: - for (i = i - 1; i >= 0; i--) - gpio_free(gpio_ext->data[i]); - i = gpio_ext->num_addr; -err_free_addr: - for (i = i - 1; i >= 0; i--) - gpio_free(gpio_ext->addr[i]); - - return err; -} - -static void gpio_ext_free(struct netxbig_gpio_ext *gpio_ext) -{ - int i; - - gpio_free(gpio_ext->enable); - for (i = gpio_ext->num_addr - 1; i >= 0; i--) - gpio_free(gpio_ext->addr[i]); - for (i = gpio_ext->num_data - 1; i >= 0; i--) - gpio_free(gpio_ext->data[i]); } /* @@ -141,11 +124,6 @@ struct netxbig_led_data { spinlock_t lock; }; -struct netxbig_led_priv { - struct netxbig_led_platform_data *pdata; - struct netxbig_led_data leds_data[]; -}; - static int netxbig_led_get_timer_mode(enum netxbig_led_mode *mode, unsigned long delay_on, unsigned long delay_off, @@ -305,18 +283,11 @@ static struct attribute *netxbig_led_attrs[] = { }; ATTRIBUTE_GROUPS(netxbig_led); -static void delete_netxbig_led(struct netxbig_led_data *led_dat) -{ - led_classdev_unregister(&led_dat->cdev); -} - -static int create_netxbig_led(struct platform_device *pdev, int led, - struct netxbig_led_priv *priv) +static int create_netxbig_led(struct platform_device *pdev, + struct netxbig_led_platform_data *pdata, + struct netxbig_led_data *led_dat, + const struct netxbig_led *template) { - struct netxbig_led_platform_data *pdata = priv->pdata; - struct netxbig_led_data *led_dat = &priv->leds_data[led]; - const struct netxbig_led *template = &priv->pdata->leds[led]; - spin_lock_init(&led_dat->lock); led_dat->gpio_ext = pdata->gpio_ext; led_dat->cdev.name = template->name; @@ -349,7 +320,7 @@ static int create_netxbig_led(struct platform_device *pdev, int led, if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) led_dat->cdev.groups = netxbig_led_groups; - return led_classdev_register(&pdev->dev, &led_dat->cdev); + return devm_led_classdev_register(&pdev->dev, &led_dat->cdev); } #ifdef CONFIG_OF_GPIO @@ -579,7 +550,7 @@ netxbig_leds_get_of_pdata(struct device *dev, static int netxbig_led_probe(struct platform_device *pdev) { struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct netxbig_led_priv *priv; + struct netxbig_led_data *leds_data; int i; int ret; @@ -592,51 +563,28 @@ static int netxbig_led_probe(struct platform_device *pdev) return ret; } - priv = devm_kzalloc(&pdev->dev, sizeof(*priv) + - pdata->num_leds * sizeof(struct netxbig_led_data), - GFP_KERNEL); - if (!priv) + leds_data = devm_kzalloc(&pdev->dev, + pdata->num_leds * sizeof(*leds_data), + GFP_KERNEL); + if (!leds_data) return -ENOMEM; - priv->pdata = pdata; - ret = gpio_ext_init(pdata->gpio_ext); + ret = gpio_ext_init(pdev, pdata->gpio_ext); if (ret < 0) return ret; for (i = 0; i < pdata->num_leds; i++) { - ret = create_netxbig_led(pdev, i, priv); + ret = create_netxbig_led(pdev, pdata, + &leds_data[i], &pdata->leds[i]); if (ret < 0) - goto err_free_leds; + return ret; } - platform_set_drvdata(pdev, priv); - - return 0; - -err_free_leds: - for (i = i - 1; i >= 0; i--) - delete_netxbig_led(&priv->leds_data[i]); - - gpio_ext_free(pdata->gpio_ext); - return ret; -} - -static int netxbig_led_remove(struct platform_device *pdev) -{ - struct netxbig_led_priv *priv = platform_get_drvdata(pdev); - struct netxbig_led_platform_data *pdata = priv->pdata; - int i; - - for (i = 0; i < pdata->num_leds; i++) - delete_netxbig_led(&priv->leds_data[i]); - - gpio_ext_free(pdata->gpio_ext); return 0; } static struct platform_driver netxbig_led_driver = { .probe = netxbig_led_probe, - .remove = netxbig_led_remove, .driver = { .name = "leds-netxbig", .of_match_table = of_match_ptr(of_netxbig_leds_match), -- cgit v0.10.2 From 7b9d9d88158e99a6a17a292ec4ec47105a771c4f Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Sat, 26 Sep 2015 23:02:38 +0200 Subject: leds: netxbig: set led_classdev max_brightness This patch sets the led_classdev max_brightness to the maximum level value supported by hardware. This allows to get rid of the brightness conversion operation (from software [0:LED_FULL] to hardware ranges) in brightness_set(). Signed-off-by: Simon Guinot Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index b166fd9..4b88b93 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c @@ -116,7 +116,6 @@ struct netxbig_led_data { int mode_addr; int *mode_val; int bright_addr; - int bright_max; struct netxbig_led_timer *timer; int num_timer; enum netxbig_led_mode mode; @@ -178,7 +177,7 @@ static void netxbig_led_set(struct led_classdev *led_cdev, struct netxbig_led_data *led_dat = container_of(led_cdev, struct netxbig_led_data, cdev); enum netxbig_led_mode mode; - int mode_val, bright_val; + int mode_val; int set_brightness = 1; unsigned long flags; @@ -204,12 +203,9 @@ static void netxbig_led_set(struct led_classdev *led_cdev, * SATA LEDs. So, change the brightness setting for a single * SATA LED will affect all the others. */ - if (set_brightness) { - bright_val = DIV_ROUND_UP(value * led_dat->bright_max, - LED_FULL); + if (set_brightness) gpio_ext_set_value(led_dat->gpio_ext, - led_dat->bright_addr, bright_val); - } + led_dat->bright_addr, value); spin_unlock_irqrestore(&led_dat->lock, flags); } @@ -306,11 +302,11 @@ static int create_netxbig_led(struct platform_device *pdev, */ led_dat->sata = 0; led_dat->cdev.brightness = LED_OFF; + led_dat->cdev.max_brightness = template->bright_max; led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; led_dat->mode_addr = template->mode_addr; led_dat->mode_val = template->mode_val; led_dat->bright_addr = template->bright_addr; - led_dat->bright_max = template->bright_max; led_dat->timer = pdata->timer; led_dat->num_timer = pdata->num_timer; /* -- cgit v0.10.2 From 79653fbb3365002899e7d25ec5ca96aff4241ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 8 Oct 2015 12:35:52 +0200 Subject: leds-bcm6328: print invalid LED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print invalid LED instead of warning only about maximum LED value. Signed-off-by: Álvaro Fernández Rojas Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c index 1793727..e1c1955 100644 --- a/drivers/leds/leds-bcm6328.c +++ b/drivers/leds/leds-bcm6328.c @@ -373,7 +373,7 @@ static int bcm6328_leds_probe(struct platform_device *pdev) continue; if (reg >= BCM6328_LED_MAX_COUNT) { - dev_err(dev, "invalid LED (>= %d)\n", + dev_err(dev, "invalid LED (%u >= %d)\n", reg, BCM6328_LED_MAX_COUNT); continue; } -- cgit v0.10.2 From d8fe1606d1a7181c877d8b1727cdcfb82f76e91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 8 Oct 2015 12:35:53 +0200 Subject: leds-bcm6328: simplify and improve default-state handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch simplifies and improves the code related to default-state handling. It also changes the code to power off the LEDs by default. Signed-off-by: Álvaro Fernández Rojas Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c index e1c1955..bf063fa 100644 --- a/drivers/leds/leds-bcm6328.c +++ b/drivers/leds/leds-bcm6328.c @@ -281,11 +281,10 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg, "linux,default-trigger", NULL); + spin_lock_irqsave(lock, flags); if (!of_property_read_string(nc, "default-state", &state)) { - spin_lock_irqsave(lock, flags); if (!strcmp(state, "on")) { led->cdev.brightness = LED_FULL; - bcm6328_led_mode(led, BCM6328_LED_MODE_ON); } else if (!strcmp(state, "keep")) { void __iomem *mode; unsigned long val, shift; @@ -296,21 +295,28 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg, else mode = mem + BCM6328_REG_MODE_LO; - val = bcm6328_led_read(mode) >> (shift % 16); + val = bcm6328_led_read(mode) >> + BCM6328_LED_SHIFT(shift % 16); val &= BCM6328_LED_MODE_MASK; - if (val == BCM6328_LED_MODE_ON) + if ((led->active_low && val == BCM6328_LED_MODE_ON) || + (!led->active_low && val == BCM6328_LED_MODE_OFF)) led->cdev.brightness = LED_FULL; - else { + else led->cdev.brightness = LED_OFF; - bcm6328_led_mode(led, BCM6328_LED_MODE_OFF); - } } else { led->cdev.brightness = LED_OFF; - bcm6328_led_mode(led, BCM6328_LED_MODE_OFF); } - spin_unlock_irqrestore(lock, flags); + } else { + led->cdev.brightness = LED_OFF; } + if ((led->active_low && led->cdev.brightness == LED_FULL) || + (!led->active_low && led->cdev.brightness == LED_OFF)) + bcm6328_led_mode(led, BCM6328_LED_MODE_ON); + else + bcm6328_led_mode(led, BCM6328_LED_MODE_OFF); + spin_unlock_irqrestore(lock, flags); + led->cdev.brightness_set = bcm6328_led_set; led->cdev.blink_set = bcm6328_blink_set; -- cgit v0.10.2 From 9f82c778ce17789a038351a411ff65cd41033c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 8 Oct 2015 12:35:54 +0200 Subject: leds-bcm6328: add more init configuration options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds more init register configuration options: - Serial LEDs multiplexing. - Serial LEDs clock signal low/high polarity. - Serial LEDs data signal low/high polarity. - Serial LEDs shift direction inverted/normal. Signed-off-by: Álvaro Fernández Rojas Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c index bf063fa..18de094 100644 --- a/drivers/leds/leds-bcm6328.c +++ b/drivers/leds/leds-bcm6328.c @@ -41,6 +41,11 @@ #define BCM6328_SERIAL_LED_SHIFT_DIR BIT(16) #define BCM6328_LED_SHIFT_TEST BIT(30) #define BCM6328_LED_TEST BIT(31) +#define BCM6328_INIT_MASK (BCM6328_SERIAL_LED_EN | \ + BCM6328_SERIAL_LED_MUX | \ + BCM6328_SERIAL_LED_CLK_NPOL | \ + BCM6328_SERIAL_LED_DATA_PPOL | \ + BCM6328_SERIAL_LED_SHIFT_DIR) #define BCM6328_LED_MODE_MASK 3 #define BCM6328_LED_MODE_OFF 0 @@ -366,9 +371,17 @@ static int bcm6328_leds_probe(struct platform_device *pdev) bcm6328_led_write(mem + BCM6328_REG_LNKACTSEL_LO, 0); val = bcm6328_led_read(mem + BCM6328_REG_INIT); - val &= ~BCM6328_SERIAL_LED_EN; + val &= ~(BCM6328_INIT_MASK); if (of_property_read_bool(np, "brcm,serial-leds")) val |= BCM6328_SERIAL_LED_EN; + if (of_property_read_bool(np, "brcm,serial-mux")) + val |= BCM6328_SERIAL_LED_MUX; + if (of_property_read_bool(np, "brcm,serial-clk-low")) + val |= BCM6328_SERIAL_LED_CLK_NPOL; + if (!of_property_read_bool(np, "brcm,serial-dat-low")) + val |= BCM6328_SERIAL_LED_DATA_PPOL; + if (!of_property_read_bool(np, "brcm,serial-shift-inv")) + val |= BCM6328_SERIAL_LED_SHIFT_DIR; bcm6328_led_write(mem + BCM6328_REG_INIT, val); for_each_available_child_of_node(np, child) { -- cgit v0.10.2 From 1d3ff22d633d35048c35c3deeead7ab116cebc32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 8 Oct 2015 12:35:55 +0200 Subject: Documentation: leds: update DT bindings for leds-bcm6328 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds latest DT bindings for leds-bcm6328 init register configuration. Signed-off-by: Álvaro Fernández Rojas Signed-off-by: Jacek Anaszewski diff --git a/Documentation/devicetree/bindings/leds/leds-bcm6328.txt b/Documentation/devicetree/bindings/leds/leds-bcm6328.txt index f9e36ad..3f48c1e 100644 --- a/Documentation/devicetree/bindings/leds/leds-bcm6328.txt +++ b/Documentation/devicetree/bindings/leds/leds-bcm6328.txt @@ -29,6 +29,14 @@ Required properties: Optional properties: - brcm,serial-leds : Boolean, enables Serial LEDs. Default : false + - brcm,serial-mux : Boolean, enables Serial LEDs multiplexing. + Default : false + - brcm,serial-clk-low : Boolean, makes clock signal active low. + Default : false + - brcm,serial-dat-low : Boolean, makes data signal active low. + Default : false + - brcm,serial-shift-inv : Boolean, inverts Serial LEDs shift direction. + Default : false Each LED is represented as a sub-node of the brcm,bcm6328-leds device. @@ -110,6 +118,8 @@ Scenario 2 : BCM63268 with Serial/GPHY0 LEDs #size-cells = <0>; reg = <0x10001900 0x24>; brcm,serial-leds; + brcm,serial-dat-low; + brcm,serial-shift-inv; gphy0_spd0@0 { reg = <0>; -- cgit v0.10.2 From 707f33ed85ff423016674d27bb2e60fe8fa352ce Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Tue, 13 Oct 2015 07:17:12 +0200 Subject: leds: leds-gpio: add shutdown function add a shutdown function for setting the gpio-leds into off state when shuting down. Signed-off-by: Heiko Schocher Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index af1876a..5db4515 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -291,9 +291,22 @@ static int gpio_led_remove(struct platform_device *pdev) return 0; } +static void gpio_led_shutdown(struct platform_device *pdev) +{ + struct gpio_leds_priv *priv = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < priv->num_leds; i++) { + struct gpio_led_data *led = &priv->leds[i]; + + gpio_led_set(&led->cdev, LED_OFF); + } +} + static struct platform_driver gpio_led_driver = { .probe = gpio_led_probe, .remove = gpio_led_remove, + .shutdown = gpio_led_shutdown, .driver = { .name = "leds-gpio", .of_match_table = of_gpio_leds_match, -- cgit v0.10.2 From d43986143463690642bac8897196496d4c776269 Mon Sep 17 00:00:00 2001 From: Fida Mohammad Date: Fri, 16 Oct 2015 14:33:03 -0700 Subject: leds: leds-locomo.c: Use devm_led_classdev_register Use resource managed function devm_led_classdev_register to make initialisation path simpler. Also removed redundant led_classdev_unregister function. Signed-off-by: Fida Mohammad Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c index 80ba048..24c4b53 100644 --- a/drivers/leds/leds-locomo.c +++ b/drivers/leds/leds-locomo.c @@ -59,23 +59,13 @@ static int locomoled_probe(struct locomo_dev *ldev) { int ret; - ret = led_classdev_register(&ldev->dev, &locomo_led0); + ret = devm_led_classdev_register(&ldev->dev, &locomo_led0); if (ret < 0) return ret; - ret = led_classdev_register(&ldev->dev, &locomo_led1); - if (ret < 0) - led_classdev_unregister(&locomo_led0); - - return ret; + return devm_led_classdev_register(&ldev->dev, &locomo_led1); } -static int locomoled_remove(struct locomo_dev *dev) -{ - led_classdev_unregister(&locomo_led0); - led_classdev_unregister(&locomo_led1); - return 0; -} static struct locomo_driver locomoled_driver = { .drv = { @@ -83,7 +73,6 @@ static struct locomo_driver locomoled_driver = { }, .devid = LOCOMO_DEVID_LED, .probe = locomoled_probe, - .remove = locomoled_remove, }; static int __init locomoled_init(void) -- cgit v0.10.2 From 81aad9f81e6d89819f12656bd38df9ef639dbe45 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Sat, 17 Oct 2015 01:47:55 +0530 Subject: leds: leds-menf21bmc.c: Use devm_led_class_register Use resource-managed function devm_led_classdev_register instead of led_classdev_register, consequently remove redundant menf21bmc_led_remove function. Also drop the unneeded label err_free_leds. Signed-off-by: Muhammad Falak R Wani Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-menf21bmc.c b/drivers/leds/leds-menf21bmc.c index 4b9eea8..dec2a6e 100644 --- a/drivers/leds/leds-menf21bmc.c +++ b/drivers/leds/leds-menf21bmc.c @@ -87,36 +87,20 @@ static int menf21bmc_led_probe(struct platform_device *pdev) leds[i].cdev.name = leds[i].name; leds[i].cdev.brightness_set = menf21bmc_led_set; leds[i].i2c_client = i2c_client; - ret = led_classdev_register(&pdev->dev, &leds[i].cdev); - if (ret < 0) - goto err_free_leds; + ret = devm_led_classdev_register(&pdev->dev, &leds[i].cdev); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register LED device\n"); + return ret; + } } dev_info(&pdev->dev, "MEN 140F21P00 BMC LED device enabled\n"); return 0; -err_free_leds: - dev_err(&pdev->dev, "failed to register LED device\n"); - - for (i = i - 1; i >= 0; i--) - led_classdev_unregister(&leds[i].cdev); - - return ret; -} - -static int menf21bmc_led_remove(struct platform_device *pdev) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(leds); i++) - led_classdev_unregister(&leds[i].cdev); - - return 0; } static struct platform_driver menf21bmc_led = { .probe = menf21bmc_led_probe, - .remove = menf21bmc_led_remove, .driver = { .name = "menf21bmc_led", }, -- cgit v0.10.2 From 511676230b56249ecb613298f95f9910684fcb4f Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Sat, 17 Oct 2015 05:02:57 +0530 Subject: leds: leds-net48xx: Use devm_led_classdev_register Use devm_led_classdev_register instead of led_classdev_register, removing the redundant net48xx_led_remove function. Signed-off-by: Muhammad Falak R Wani Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-net48xx.c b/drivers/leds/leds-net48xx.c index ec3a2e8..0d214c2 100644 --- a/drivers/leds/leds-net48xx.c +++ b/drivers/leds/leds-net48xx.c @@ -39,18 +39,11 @@ static struct led_classdev net48xx_error_led = { static int net48xx_led_probe(struct platform_device *pdev) { - return led_classdev_register(&pdev->dev, &net48xx_error_led); -} - -static int net48xx_led_remove(struct platform_device *pdev) -{ - led_classdev_unregister(&net48xx_error_led); - return 0; + return devm_led_classdev_register(&pdev->dev, &net48xx_error_led); } static struct platform_driver net48xx_led_driver = { .probe = net48xx_led_probe, - .remove = net48xx_led_remove, .driver = { .name = DRVNAME, }, -- cgit v0.10.2 From 10238adb6f2bcc6c418188ef3425ea57297fa3a6 Mon Sep 17 00:00:00 2001 From: Ingi Kim Date: Thu, 22 Oct 2015 10:14:07 +0900 Subject: leds: aat1290: Fix property naming of flash-timeout-us flash-timeout-us property name is changed to flash-max-timeout-us. This patch fixes that name. Signed-off-by: Ingi Kim Signed-off-by: Jacek Anaszewski diff --git a/Documentation/devicetree/bindings/leds/leds-aat1290.txt b/Documentation/devicetree/bindings/leds/leds-aat1290.txt index c05ed91..85c0c58 100644 --- a/Documentation/devicetree/bindings/leds/leds-aat1290.txt +++ b/Documentation/devicetree/bindings/leds/leds-aat1290.txt @@ -27,9 +27,9 @@ Required properties of the LED child node: - flash-max-microamp : see Documentation/devicetree/bindings/leds/common.txt Maximum flash LED supply current can be calculated using following formula: I = 1A * 162kohm / Rset. -- flash-timeout-us : see Documentation/devicetree/bindings/leds/common.txt - Maximum flash timeout can be calculated using following - formula: T = 8.82 * 10^9 * Ct. +- flash-max-timeout-us : see Documentation/devicetree/bindings/leds/common.txt + Maximum flash timeout can be calculated using following + formula: T = 8.82 * 10^9 * Ct. Optional properties of the LED child node: - label : see Documentation/devicetree/bindings/leds/common.txt @@ -54,7 +54,7 @@ aat1290 { label = "aat1290-flash"; led-max-microamp = <520833>; flash-max-microamp = <1012500>; - flash-timeout-us = <1940000>; + flash-max-timeout-us = <1940000>; }; }; -- cgit v0.10.2 From e9aadb864f04f1f7c7f8713fead64a2370be940d Mon Sep 17 00:00:00 2001 From: Fida Mohammad Date: Wed, 21 Oct 2015 03:58:35 -0700 Subject: leds: leds-wrap.c: Use devm_led_classdev_register Use of resource managed function devm_led_classdev_register to make initialization path simpler. Also removed redundant remove function. Signed-off-by: Fida Mohammad Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-wrap.c b/drivers/leds/leds-wrap.c index 1ba3def..473fb6b 100644 --- a/drivers/leds/leds-wrap.c +++ b/drivers/leds/leds-wrap.c @@ -76,39 +76,19 @@ static int wrap_led_probe(struct platform_device *pdev) { int ret; - ret = led_classdev_register(&pdev->dev, &wrap_power_led); + ret = devm_led_classdev_register(&pdev->dev, &wrap_power_led); if (ret < 0) return ret; - ret = led_classdev_register(&pdev->dev, &wrap_error_led); + ret = devm_led_classdev_register(&pdev->dev, &wrap_error_led); if (ret < 0) - goto err1; - - ret = led_classdev_register(&pdev->dev, &wrap_extra_led); - if (ret < 0) - goto err2; - - return ret; - -err2: - led_classdev_unregister(&wrap_error_led); -err1: - led_classdev_unregister(&wrap_power_led); - - return ret; -} + return ret; -static int wrap_led_remove(struct platform_device *pdev) -{ - led_classdev_unregister(&wrap_power_led); - led_classdev_unregister(&wrap_error_led); - led_classdev_unregister(&wrap_extra_led); - return 0; + return devm_led_classdev_register(&pdev->dev, &wrap_extra_led); } static struct platform_driver wrap_led_driver = { .probe = wrap_led_probe, - .remove = wrap_led_remove, .driver = { .name = DRVNAME, }, -- cgit v0.10.2 From dde4afe7656084b7886f3b721530c32209842390 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 24 Oct 2015 16:42:27 +0200 Subject: powerpc/powernv: add missing of_node_put for_each_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression root,e; local idexpression child; @@ for_each_child_of_node(root, child) { ... when != of_node_put(child) when != e = child ( return child; | + of_node_put(child); ? return ...; ) ... } // Signed-off-by: Julia Lawall Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-powernv.c b/drivers/leds/leds-powernv.c index 2c5c5b1..1e75e1f 100644 --- a/drivers/leds/leds-powernv.c +++ b/drivers/leds/leds-powernv.c @@ -262,15 +262,19 @@ static int powernv_led_classdev(struct platform_device *pdev, while ((cur = of_prop_next_string(p, cur)) != NULL) { powernv_led = devm_kzalloc(dev, sizeof(*powernv_led), GFP_KERNEL); - if (!powernv_led) + if (!powernv_led) { + of_node_put(np); return -ENOMEM; + } powernv_led->common = powernv_led_common; powernv_led->loc_code = (char *)np->name; rc = powernv_led_create(dev, powernv_led, cur); - if (rc) + if (rc) { + of_node_put(np); return rc; + } } /* while end */ } -- cgit v0.10.2 From 4b6ba5e28b2903fa8b51c6d5fdafb2979fe6eeab Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 24 Oct 2015 16:42:28 +0200 Subject: leds: bcm6358: add missing of_node_put for_each_available_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression root,e; local idexpression child; @@ for_each_available_child_of_node(root, child) { ... when != of_node_put(child) when != e = child ( return child; | + of_node_put(child); ? return ...; ) ... } // Signed-off-by: Julia Lawall Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-bcm6358.c b/drivers/leds/leds-bcm6358.c index 7ea3526..82b4ee1 100644 --- a/drivers/leds/leds-bcm6358.c +++ b/drivers/leds/leds-bcm6358.c @@ -215,8 +215,10 @@ static int bcm6358_leds_probe(struct platform_device *pdev) } rc = bcm6358_led(dev, child, reg, mem, lock); - if (rc < 0) + if (rc < 0) { + of_node_put(child); return rc; + } } return 0; -- cgit v0.10.2 From 6cc7624415466022749a868c159ac68367bc9a0e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 24 Oct 2015 16:42:29 +0200 Subject: leds: bcm6328: add missing of_node_put for_each_available_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression root,e; local idexpression child; @@ for_each_available_child_of_node(root, child) { ... when != of_node_put(child) when != e = child ( return child; | + of_node_put(child); ? return ...; ) ... } // Signed-off-by: Julia Lawall Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c index 18de094..c7ea5c6 100644 --- a/drivers/leds/leds-bcm6328.c +++ b/drivers/leds/leds-bcm6328.c @@ -403,8 +403,10 @@ static int bcm6328_leds_probe(struct platform_device *pdev) rc = bcm6328_led(dev, child, reg, mem, lock, blink_leds, blink_delay); - if (rc < 0) + if (rc < 0) { + of_node_put(child); return rc; + } } return 0; -- cgit v0.10.2 From ffdc307d038f02617041f8e5c7e3cd00a1706a2a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 24 Oct 2015 16:42:30 +0200 Subject: leds: 88pm860x: add missing of_node_put for_each_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ local idexpression n; expression e,r; @@ for_each_child_of_node(r,n) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // Signed-off-by: Julia Lawall Signed-off-by: Jacek Anaszewski diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 1497a09..7870840 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c @@ -142,6 +142,7 @@ static int pm860x_led_dt_init(struct platform_device *pdev, of_property_read_u32(np, "marvell,88pm860x-iset", &iset); data->iset = PM8606_LED_CURRENT(iset); + of_node_put(np); break; } } -- cgit v0.10.2