GIT 0dee8296b653bde8c43f9fdb5c909a695b8a4637 git://git.o-hand.com/linux-rpurdie-leds#for-mm commit Author: Raphael Assenat Date: Tue Feb 27 19:49:53 2007 +0000 leds: Add generic GPIO LED driver This patch adds support for GPIO connected leds via the new GPIO framework. Information about leds (gpio, polarity, name, default trigger) is passed to the driver via platform_data. Signed-off-by: Raphael Assenat Signed-off-by: Richard Purdie commit c8d8e20afe347d66571f0fdad3a4bf99c15ffbbe Author: Florian Fainelli Date: Mon Feb 12 23:16:27 2007 +0000 leds: Add support for Cobalt Server front LED Add support for Cobalt Server front LED (MIPS) Signed-off-by: Florian Fainell Signed-off-by: Richard Purdie commit dc1d072b02f2de1eacfeaa4e6923beb2ef05bae6 Author: Arnaud Patard Date: Mon Feb 12 23:09:32 2007 +0000 leds: Add IPAQ h1940 LEDs support This patch adds the support for the IPAQ h1940 leds. In order to create the amber led (used for the battery charging), the red and green leds are set to the same default trigger. Due to hardware limitations, the blue led can only be set in blinking mode. Signed-off-by: Arnaud Patard Signed-off-by: Richard Purdie drivers/leds/Kconfig | 23 ++++++ drivers/leds/Makefile | 6 ++ drivers/leds/leds-gpio.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/leds.h | 14 ++++ 4 files changed, 222 insertions(+), 0 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 80acd08..0d496bf 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -82,6 +82,7 @@ config LEDS_WRAP help This option enables support for the PCEngines WRAP programmable LEDs. +<<<<<<< HEAD/drivers/leds/Kconfig config LEDS_H1940 tristate "LED Support for iPAQ H1940 device" depends LEDS_CLASS && ARCH_H1940 @@ -94,6 +95,28 @@ config LEDS_COBALT help This option enables support for the front LED on Cobalt Server +======= +config LEDS_H1940 + tristate "LED Support for iPAQ H1940 device" + depends LEDS_CLASS && ARCH_H1940 + help + This option enables support for the LEDs on the h1940. + +config LEDS_COBALT + tristate "LED Support for Cobalt Server front LED" + depends on LEDS_CLASS && MIPS_COBALT + help + This option enables support for the front LED on Cobalt Server + +config LEDS_GPIO + tristate "LED Support for GPIO connected LEDs" + depends on LEDS_CLASS + help + This option enables support for the LEDs connected to GPIO + outputs. To be useful the particular board must have LEDs + and they must be connected to the GPIO lines. + +>>>>>>> /drivers/leds/Kconfig comment "LED Triggers" config LEDS_TRIGGERS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index aa2c18e..d970ff8 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -14,8 +14,14 @@ obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c2 obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o +<<<<<<< HEAD/drivers/leds/Makefile obj-$(CONFIG_LEDS_H1940) += leds-h1940.o obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o +======= +obj-$(CONFIG_LEDS_H1940) += leds-h1940.o +obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o +obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o +>>>>>>> /drivers/leds/Makefile # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c new file mode 100644 index 0000000..04fa7fd --- /dev/null +++ b/drivers/leds/leds-gpio.c @@ -0,0 +1,179 @@ +/* + * LEDs driver for GPIOs + * + * Copyright (C) 2007 8D Technologies inc. + * Raphael Assenat + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include + +struct gpio_led_data { + struct led_classdev cdev; + unsigned gpio; + u8 active_low; +}; + + +static void gpio_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct gpio_led_data *led_dat = + container_of(led_cdev, struct gpio_led_data, cdev); + int level; + + if (value == LED_OFF) + level = 0; + else + level = 1; + + if (led_dat->active_low) + level = !level; + + gpio_set_value(led_dat->gpio, level); +} + +static int __init gpio_led_probe(struct platform_device *pdev) +{ + struct gpio_led_platform_data *pdata = pdev->dev.platform_data; + struct gpio_led *cur_led; + struct gpio_led_data *leds_data, *led_dat; + int level, i, ret = 0; + + if (!pdata) + return -EBUSY; + + leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds, + GFP_KERNEL); + if (!leds_data) + return -ENOMEM; + + for (i = 0; i < pdata->num_leds; i++) { + cur_led = &pdata->leds[i]; + led_dat = &leds_data[i]; + + led_dat->cdev.name = cur_led->name; + led_dat->cdev.default_trigger = cur_led->default_trigger; + led_dat->gpio = cur_led->gpio; + led_dat->active_low = cur_led->active_low; + led_dat->cdev.brightness_set = gpio_led_set; + + ret = gpio_request(led_dat->gpio, led_dat->cdev.name); + if (ret < 0) + goto err; + + gpio_direction_output(led_dat->gpio); + + level = gpio_get_value(led_dat->gpio); + if (led_dat->active_low) + level = !level; + + led_dat->cdev.brightness = level ? LED_FULL : LED_OFF; + + ret = led_classdev_register(&pdev->dev, &led_dat->cdev); + if (ret < 0) { + gpio_free(led_dat->gpio); + goto err; + } + } + + platform_set_drvdata(pdev, leds_data); + + return 0; + +err: + if (i > 0) { + for (i = i - 1; i >= 0; i--) { + led_classdev_unregister(&leds_data[i].cdev); + gpio_free(leds_data[i].gpio); + } + } + kfree(leds_data); + + return ret; +} + +static int __exit gpio_led_remove(struct platform_device *pdev) +{ + int i; + struct gpio_led_platform_data *pdata = pdev->dev.platform_data; + struct gpio_led_data *leds_data; + + leds_data = platform_get_drvdata(pdev); + + for (i = 0; i < pdata->num_leds; i++) { + led_classdev_unregister(&leds_data[i].cdev); + gpio_free(leds_data[i].gpio); + } + + kfree(leds_data); + + return 0; +} + +#ifdef CONFIG_PM +static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct gpio_led_platform_data *pdata = pdev->dev.platform_data; + struct gpio_led_data *leds_data; + int i; + + leds_data = platform_get_drvdata(pdev); + + for (i = 0; i < pdata->num_leds; i++) + led_classdev_suspend(&leds_data[i].cdev); + + return 0; +} + +static int gpio_led_resume(struct platform_device *pdev) +{ + struct gpio_led_platform_data *pdata = pdev->dev.platform_data; + struct gpio_led_data *leds_data; + int i; + + leds_data = platform_get_drvdata(pdev); + + for (i = 0; i < pdata->num_leds; i++) + led_classdev_resume(&leds_data[i].cdev); + + return 0; +} +#else +#define gpio_led_suspend NULL +#define gpio_led_resume NULL +#endif + +static struct platform_driver gpio_led_driver = { + .remove = __exit_p(gpio_led_remove), + .suspend = gpio_led_suspend, + .resume = gpio_led_resume, + .driver = { + .name = "leds-gpio", + .owner = THIS_MODULE, + }, +}; + +static int __init gpio_led_init(void) +{ + return platform_driver_probe(&gpio_led_driver, gpio_led_probe); +} + +static void __exit gpio_led_exit(void) +{ + platform_driver_unregister(&gpio_led_driver); +} + +module_init(gpio_led_init); +module_exit(gpio_led_exit); + +MODULE_AUTHOR("Raphael Assenat "); +MODULE_DESCRIPTION("GPIO LED driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds.h b/include/linux/leds.h index 88afcef..059abfe 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -110,4 +110,18 @@ #else #define ledtrig_ide_activity() do {} while(0) #endif +/* For the leds-gpio driver */ +struct gpio_led { + const char *name; + char *default_trigger; + unsigned gpio; + u8 active_low; +}; + +struct gpio_led_platform_data { + int num_leds; + struct gpio_led *leds; +}; + + #endif /* __LINUX_LEDS_H_INCLUDED */