aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/leds/Kconfig8
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-gpio.c174
3 files changed, 183 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 87d2046f866c..9ce3ca109c2f 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -95,6 +95,14 @@ config LEDS_COBALT
95 help 95 help
96 This option enables support for the front LED on Cobalt Server 96 This option enables support for the front LED on Cobalt Server
97 97
98config LEDS_GPIO
99 tristate "LED Support for GPIO connected LEDs"
100 depends on LEDS_CLASS && GENERIC_GPIO
101 help
102 This option enables support for the LEDs connected to GPIO
103 outputs. To be useful the particular board must have LEDs
104 and they must be connected to the GPIO lines.
105
98comment "LED Triggers" 106comment "LED Triggers"
99 107
100config LEDS_TRIGGERS 108config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index aa2c18efa5b2..f8995c9bc2ea 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
16obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o 16obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
17obj-$(CONFIG_LEDS_H1940) += leds-h1940.o 17obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
18obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o 18obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o
19obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
19 20
20# LED Triggers 21# LED Triggers
21obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o 22obj-$(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 000000000000..431dcb61902c
--- /dev/null
+++ b/drivers/leds/leds-gpio.c
@@ -0,0 +1,174 @@
1/*
2 * LEDs driver for GPIOs
3 *
4 * Copyright (C) 2007 8D Technologies inc.
5 * Raphael Assenat <raph@8d.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/platform_device.h>
15#include <linux/leds.h>
16#include <asm/gpio.h>
17
18struct gpio_led_data {
19 struct led_classdev cdev;
20 unsigned gpio;
21 u8 active_low;
22};
23
24
25static void gpio_led_set(struct led_classdev *led_cdev,
26 enum led_brightness value)
27{
28 struct gpio_led_data *led_dat =
29 container_of(led_cdev, struct gpio_led_data, cdev);
30 int level;
31
32 if (value == LED_OFF)
33 level = 0;
34 else
35 level = 1;
36
37 if (led_dat->active_low)
38 level = !level;
39
40 gpio_set_value(led_dat->gpio, level);
41}
42
43static int __init gpio_led_probe(struct platform_device *pdev)
44{
45 struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
46 struct gpio_led *cur_led;
47 struct gpio_led_data *leds_data, *led_dat;
48 int i, ret = 0;
49
50 if (!pdata)
51 return -EBUSY;
52
53 leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds,
54 GFP_KERNEL);
55 if (!leds_data)
56 return -ENOMEM;
57
58 for (i = 0; i < pdata->num_leds; i++) {
59 cur_led = &pdata->leds[i];
60 led_dat = &leds_data[i];
61
62 led_dat->cdev.name = cur_led->name;
63 led_dat->cdev.default_trigger = cur_led->default_trigger;
64 led_dat->gpio = cur_led->gpio;
65 led_dat->active_low = cur_led->active_low;
66 led_dat->cdev.brightness_set = gpio_led_set;
67 led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : LED_OFF;
68
69 ret = gpio_request(led_dat->gpio, led_dat->cdev.name);
70 if (ret < 0)
71 goto err;
72
73 gpio_direction_output(led_dat->gpio, led_dat->active_low);
74
75 ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
76 if (ret < 0) {
77 gpio_free(led_dat->gpio);
78 goto err;
79 }
80 }
81
82 platform_set_drvdata(pdev, leds_data);
83
84 return 0;
85
86err:
87 if (i > 0) {
88 for (i = i - 1; i >= 0; i--) {
89 led_classdev_unregister(&leds_data[i].cdev);
90 gpio_free(leds_data[i].gpio);
91 }
92 }
93 kfree(leds_data);
94
95 return ret;
96}
97
98static int __exit gpio_led_remove(struct platform_device *pdev)
99{
100 int i;
101 struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
102 struct gpio_led_data *leds_data;
103
104 leds_data = platform_get_drvdata(pdev);
105
106 for (i = 0; i < pdata->num_leds; i++) {
107 led_classdev_unregister(&leds_data[i].cdev);
108 gpio_free(leds_data[i].gpio);
109 }
110
111 kfree(leds_data);
112
113 return 0;
114}
115
116#ifdef CONFIG_PM
117static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state)
118{
119 struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
120 struct gpio_led_data *leds_data;
121 int i;
122
123 leds_data = platform_get_drvdata(pdev);
124
125 for (i = 0; i < pdata->num_leds; i++)
126 led_classdev_suspend(&leds_data[i].cdev);
127
128 return 0;
129}
130
131static int gpio_led_resume(struct platform_device *pdev)
132{
133 struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
134 struct gpio_led_data *leds_data;
135 int i;
136
137 leds_data = platform_get_drvdata(pdev);
138
139 for (i = 0; i < pdata->num_leds; i++)
140 led_classdev_resume(&leds_data[i].cdev);
141
142 return 0;
143}
144#else
145#define gpio_led_suspend NULL
146#define gpio_led_resume NULL
147#endif
148
149static struct platform_driver gpio_led_driver = {
150 .remove = __exit_p(gpio_led_remove),
151 .suspend = gpio_led_suspend,
152 .resume = gpio_led_resume,
153 .driver = {
154 .name = "leds-gpio",
155 .owner = THIS_MODULE,
156 },
157};
158
159static int __init gpio_led_init(void)
160{
161 return platform_driver_probe(&gpio_led_driver, gpio_led_probe);
162}
163
164static void __exit gpio_led_exit(void)
165{
166 platform_driver_unregister(&gpio_led_driver);
167}
168
169module_init(gpio_led_init);
170module_exit(gpio_led_exit);
171
172MODULE_AUTHOR("Raphael Assenat <raph@8d.com>");
173MODULE_DESCRIPTION("GPIO LED driver");
174MODULE_LICENSE("GPL");