aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds/leds-gpio.c
diff options
context:
space:
mode:
authorJacek Anaszewski <j.anaszewski@samsung.com>2015-08-20 09:52:32 -0400
committerJacek Anaszewski <j.anaszewski@samsung.com>2016-01-04 03:57:35 -0500
commitd5b8a09000da3dcd79649293121afe4439153c7a (patch)
treed5e32f5e6600ec3ecaa945fd12581744c6de55b7 /drivers/leds/leds-gpio.c
parent0dd756f7677a519a1d52a94e74d179e0af39e2ec (diff)
leds: gpio: Remove work queue
Now the core implements the work queue, remove it from the drivers, and switch to using brightness_set_blocking op. Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com> Cc: Raphael Assenat <raph@8d.com>
Diffstat (limited to 'drivers/leds/leds-gpio.c')
-rw-r--r--drivers/leds/leds-gpio.c62
1 files changed, 22 insertions, 40 deletions
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 5db4515a4fd7..7bc53280dbfd 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -20,32 +20,16 @@
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/property.h> 21#include <linux/property.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/workqueue.h>
24 23
25struct gpio_led_data { 24struct gpio_led_data {
26 struct led_classdev cdev; 25 struct led_classdev cdev;
27 struct gpio_desc *gpiod; 26 struct gpio_desc *gpiod;
28 struct work_struct work;
29 u8 new_level;
30 u8 can_sleep; 27 u8 can_sleep;
31 u8 blinking; 28 u8 blinking;
32 int (*platform_gpio_blink_set)(struct gpio_desc *desc, int state, 29 int (*platform_gpio_blink_set)(struct gpio_desc *desc, int state,
33 unsigned long *delay_on, unsigned long *delay_off); 30 unsigned long *delay_on, unsigned long *delay_off);
34}; 31};
35 32
36static void gpio_led_work(struct work_struct *work)
37{
38 struct gpio_led_data *led_dat =
39 container_of(work, struct gpio_led_data, work);
40
41 if (led_dat->blinking) {
42 led_dat->platform_gpio_blink_set(led_dat->gpiod,
43 led_dat->new_level, NULL, NULL);
44 led_dat->blinking = 0;
45 } else
46 gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);
47}
48
49static void gpio_led_set(struct led_classdev *led_cdev, 33static void gpio_led_set(struct led_classdev *led_cdev,
50 enum led_brightness value) 34 enum led_brightness value)
51{ 35{
@@ -58,23 +42,25 @@ static void gpio_led_set(struct led_classdev *led_cdev,
58 else 42 else
59 level = 1; 43 level = 1;
60 44
61 /* Setting GPIOs with I2C/etc requires a task context, and we don't 45 if (led_dat->blinking) {
62 * seem to have a reliable way to know if we're already in one; so 46 led_dat->platform_gpio_blink_set(led_dat->gpiod, level,
63 * let's just assume the worst. 47 NULL, NULL);
64 */ 48 led_dat->blinking = 0;
65 if (led_dat->can_sleep) {
66 led_dat->new_level = level;
67 schedule_work(&led_dat->work);
68 } else { 49 } else {
69 if (led_dat->blinking) { 50 if (led_dat->can_sleep)
70 led_dat->platform_gpio_blink_set(led_dat->gpiod, level, 51 gpiod_set_value_cansleep(led_dat->gpiod, level);
71 NULL, NULL); 52 else
72 led_dat->blinking = 0;
73 } else
74 gpiod_set_value(led_dat->gpiod, level); 53 gpiod_set_value(led_dat->gpiod, level);
75 } 54 }
76} 55}
77 56
57static int gpio_led_set_blocking(struct led_classdev *led_cdev,
58 enum led_brightness value)
59{
60 gpio_led_set(led_cdev, value);
61 return 0;
62}
63
78static int gpio_blink_set(struct led_classdev *led_cdev, 64static int gpio_blink_set(struct led_classdev *led_cdev,
79 unsigned long *delay_on, unsigned long *delay_off) 65 unsigned long *delay_on, unsigned long *delay_off)
80{ 66{
@@ -125,12 +111,15 @@ static int create_gpio_led(const struct gpio_led *template,
125 led_dat->cdev.name = template->name; 111 led_dat->cdev.name = template->name;
126 led_dat->cdev.default_trigger = template->default_trigger; 112 led_dat->cdev.default_trigger = template->default_trigger;
127 led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod); 113 led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod);
114 if (!led_dat->can_sleep)
115 led_dat->cdev.brightness_set = gpio_led_set;
116 else
117 led_dat->cdev.brightness_set_blocking = gpio_led_set_blocking;
128 led_dat->blinking = 0; 118 led_dat->blinking = 0;
129 if (blink_set) { 119 if (blink_set) {
130 led_dat->platform_gpio_blink_set = blink_set; 120 led_dat->platform_gpio_blink_set = blink_set;
131 led_dat->cdev.blink_set = gpio_blink_set; 121 led_dat->cdev.blink_set = gpio_blink_set;
132 } 122 }
133 led_dat->cdev.brightness_set = gpio_led_set;
134 if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) 123 if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
135 state = !!gpiod_get_value_cansleep(led_dat->gpiod); 124 state = !!gpiod_get_value_cansleep(led_dat->gpiod);
136 else 125 else
@@ -143,17 +132,9 @@ static int create_gpio_led(const struct gpio_led *template,
143 if (ret < 0) 132 if (ret < 0)
144 return ret; 133 return ret;
145 134
146 INIT_WORK(&led_dat->work, gpio_led_work);
147
148 return led_classdev_register(parent, &led_dat->cdev); 135 return led_classdev_register(parent, &led_dat->cdev);
149} 136}
150 137
151static void delete_gpio_led(struct gpio_led_data *led)
152{
153 led_classdev_unregister(&led->cdev);
154 cancel_work_sync(&led->work);
155}
156
157struct gpio_leds_priv { 138struct gpio_leds_priv {
158 int num_leds; 139 int num_leds;
159 struct gpio_led_data leds[]; 140 struct gpio_led_data leds[];
@@ -233,7 +214,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
233 214
234err: 215err:
235 for (count = priv->num_leds - 1; count >= 0; count--) 216 for (count = priv->num_leds - 1; count >= 0; count--)
236 delete_gpio_led(&priv->leds[count]); 217 led_classdev_unregister(&priv->leds[count].cdev);
237 return ERR_PTR(ret); 218 return ERR_PTR(ret);
238} 219}
239 220
@@ -265,7 +246,8 @@ static int gpio_led_probe(struct platform_device *pdev)
265 if (ret < 0) { 246 if (ret < 0) {
266 /* On failure: unwind the led creations */ 247 /* On failure: unwind the led creations */
267 for (i = i - 1; i >= 0; i--) 248 for (i = i - 1; i >= 0; i--)
268 delete_gpio_led(&priv->leds[i]); 249 led_classdev_unregister(
250 &priv->leds[i].cdev);
269 return ret; 251 return ret;
270 } 252 }
271 } 253 }
@@ -286,7 +268,7 @@ static int gpio_led_remove(struct platform_device *pdev)
286 int i; 268 int i;
287 269
288 for (i = 0; i < priv->num_leds; i++) 270 for (i = 0; i < priv->num_leds; i++)
289 delete_gpio_led(&priv->leds[i]); 271 led_classdev_unregister(&priv->leds[i].cdev);
290 272
291 return 0; 273 return 0;
292} 274}