aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds/leds-gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/leds/leds-gpio.c')
-rw-r--r--drivers/leds/leds-gpio.c174
1 files changed, 174 insertions, 0 deletions
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");