Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=22e03f3b58dfcca30f0c8de185022132459638d1
Commit:     22e03f3b58dfcca30f0c8de185022132459638d1
Parent:     8f41958bdd577731f7411c9605cfaa9db6766809
Author:     Raphael Assenat <[EMAIL PROTECTED]>
AuthorDate: Tue Feb 27 19:49:53 2007 +0000
Committer:  Richard Purdie <[EMAIL PROTECTED]>
CommitDate: Mon Jul 16 01:15:50 2007 +0100

    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 <[EMAIL PROTECTED]>
    Signed-off-by: Richard Purdie <[EMAIL PROTECTED]>
---
 drivers/leds/Kconfig     |    8 ++
 drivers/leds/Makefile    |    1 +
 drivers/leds/leds-gpio.c |  174 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/leds.h     |   14 ++++
 4 files changed, 197 insertions(+), 0 deletions(-)

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 87d2046..9ce3ca1 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -95,6 +95,14 @@ config LEDS_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 && GENERIC_GPIO
+       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.
+
 comment "LED Triggers"
 
 config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index aa2c18e..f8995c9 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_LEDS_NET48XX)            += leds-net48xx.o
 obj-$(CONFIG_LEDS_WRAP)                        += leds-wrap.o
 obj-$(CONFIG_LEDS_H1940)               += leds-h1940.o
 obj-$(CONFIG_LEDS_COBALT)              += leds-cobalt.o
+obj-$(CONFIG_LEDS_GPIO)                        += leds-gpio.o
 
 # 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..431dcb6
--- /dev/null
+++ b/drivers/leds/leds-gpio.c
@@ -0,0 +1,174 @@
+/*
+ * LEDs driver for GPIOs
+ *
+ * Copyright (C) 2007 8D Technologies inc.
+ * Raphael Assenat <[EMAIL PROTECTED]>
+ *
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/gpio.h>
+
+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 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;
+               led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : 
LED_OFF;
+
+               ret = gpio_request(led_dat->gpio, led_dat->cdev.name);
+               if (ret < 0)
+                       goto err;
+
+               gpio_direction_output(led_dat->gpio, led_dat->active_low);
+
+               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 <[EMAIL PROTECTED]>");
+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 @@ extern void ledtrig_ide_activity(void);
 #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 */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to