2 * LEDs driver for GPIOs
4 * Copyright (C) 2007 8D Technologies inc.
5 * Raphael Assenat <raph@8d.com>
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.
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/platform_device.h>
15 #include <linux/leds.h>
16 #include <linux/workqueue.h>
20 struct gpio_led_data
{
21 struct led_classdev cdev
;
23 struct work_struct work
;
27 int (*platform_gpio_blink_set
)(unsigned gpio
,
28 unsigned long *delay_on
, unsigned long *delay_off
);
31 static void gpio_led_work(struct work_struct
*work
)
33 struct gpio_led_data
*led_dat
=
34 container_of(work
, struct gpio_led_data
, work
);
36 gpio_set_value_cansleep(led_dat
->gpio
, led_dat
->new_level
);
39 static void gpio_led_set(struct led_classdev
*led_cdev
,
40 enum led_brightness value
)
42 struct gpio_led_data
*led_dat
=
43 container_of(led_cdev
, struct gpio_led_data
, cdev
);
51 if (led_dat
->active_low
)
54 /* Setting GPIOs with I2C/etc requires a task context, and we don't
55 * seem to have a reliable way to know if we're already in one; so
56 * let's just assume the worst.
58 if (led_dat
->can_sleep
) {
59 led_dat
->new_level
= level
;
60 schedule_work(&led_dat
->work
);
62 gpio_set_value(led_dat
->gpio
, level
);
65 static int gpio_blink_set(struct led_classdev
*led_cdev
,
66 unsigned long *delay_on
, unsigned long *delay_off
)
68 struct gpio_led_data
*led_dat
=
69 container_of(led_cdev
, struct gpio_led_data
, cdev
);
71 return led_dat
->platform_gpio_blink_set(led_dat
->gpio
, delay_on
, delay_off
);
74 static int gpio_led_probe(struct platform_device
*pdev
)
76 struct gpio_led_platform_data
*pdata
= pdev
->dev
.platform_data
;
77 struct gpio_led
*cur_led
;
78 struct gpio_led_data
*leds_data
, *led_dat
;
84 leds_data
= kzalloc(sizeof(struct gpio_led_data
) * pdata
->num_leds
,
89 for (i
= 0; i
< pdata
->num_leds
; i
++) {
90 cur_led
= &pdata
->leds
[i
];
91 led_dat
= &leds_data
[i
];
93 ret
= gpio_request(cur_led
->gpio
, cur_led
->name
);
97 led_dat
->cdev
.name
= cur_led
->name
;
98 led_dat
->cdev
.default_trigger
= cur_led
->default_trigger
;
99 led_dat
->gpio
= cur_led
->gpio
;
100 led_dat
->can_sleep
= gpio_cansleep(cur_led
->gpio
);
101 led_dat
->active_low
= cur_led
->active_low
;
102 if (pdata
->gpio_blink_set
) {
103 led_dat
->platform_gpio_blink_set
= pdata
->gpio_blink_set
;
104 led_dat
->cdev
.blink_set
= gpio_blink_set
;
106 led_dat
->cdev
.brightness_set
= gpio_led_set
;
107 led_dat
->cdev
.brightness
= LED_OFF
;
109 gpio_direction_output(led_dat
->gpio
, led_dat
->active_low
);
111 INIT_WORK(&led_dat
->work
, gpio_led_work
);
113 ret
= led_classdev_register(&pdev
->dev
, &led_dat
->cdev
);
115 gpio_free(led_dat
->gpio
);
120 platform_set_drvdata(pdev
, leds_data
);
126 for (i
= i
- 1; i
>= 0; i
--) {
127 led_classdev_unregister(&leds_data
[i
].cdev
);
128 cancel_work_sync(&leds_data
[i
].work
);
129 gpio_free(leds_data
[i
].gpio
);
138 static int __devexit
gpio_led_remove(struct platform_device
*pdev
)
141 struct gpio_led_platform_data
*pdata
= pdev
->dev
.platform_data
;
142 struct gpio_led_data
*leds_data
;
144 leds_data
= platform_get_drvdata(pdev
);
146 for (i
= 0; i
< pdata
->num_leds
; i
++) {
147 led_classdev_unregister(&leds_data
[i
].cdev
);
148 cancel_work_sync(&leds_data
[i
].work
);
149 gpio_free(leds_data
[i
].gpio
);
158 static int gpio_led_suspend(struct platform_device
*pdev
, pm_message_t state
)
160 struct gpio_led_platform_data
*pdata
= pdev
->dev
.platform_data
;
161 struct gpio_led_data
*leds_data
;
164 leds_data
= platform_get_drvdata(pdev
);
166 for (i
= 0; i
< pdata
->num_leds
; i
++)
167 led_classdev_suspend(&leds_data
[i
].cdev
);
172 static int gpio_led_resume(struct platform_device
*pdev
)
174 struct gpio_led_platform_data
*pdata
= pdev
->dev
.platform_data
;
175 struct gpio_led_data
*leds_data
;
178 leds_data
= platform_get_drvdata(pdev
);
180 for (i
= 0; i
< pdata
->num_leds
; i
++)
181 led_classdev_resume(&leds_data
[i
].cdev
);
186 #define gpio_led_suspend NULL
187 #define gpio_led_resume NULL
190 static struct platform_driver gpio_led_driver
= {
191 .probe
= gpio_led_probe
,
192 .remove
= __devexit_p(gpio_led_remove
),
193 .suspend
= gpio_led_suspend
,
194 .resume
= gpio_led_resume
,
197 .owner
= THIS_MODULE
,
201 static int __init
gpio_led_init(void)
203 return platform_driver_register(&gpio_led_driver
);
206 static void __exit
gpio_led_exit(void)
208 platform_driver_unregister(&gpio_led_driver
);
211 module_init(gpio_led_init
);
212 module_exit(gpio_led_exit
);
214 MODULE_AUTHOR("Raphael Assenat <raph@8d.com>");
215 MODULE_DESCRIPTION("GPIO LED driver");
216 MODULE_LICENSE("GPL");
217 MODULE_ALIAS("platform:leds-gpio");