USB: serial: option: add Luat Air72*U series products
[linux-2.6-microblaze.git] / drivers / leds / led-core.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * LED Class Core
4  *
5  * Copyright 2005-2006 Openedhand Ltd.
6  *
7  * Author: Richard Purdie <rpurdie@openedhand.com>
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/leds.h>
12 #include <linux/list.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
15 #include <linux/of.h>
16 #include <linux/property.h>
17 #include <linux/rwsem.h>
18 #include <linux/slab.h>
19 #include <uapi/linux/uleds.h>
20 #include "leds.h"
21
22 DECLARE_RWSEM(leds_list_lock);
23 EXPORT_SYMBOL_GPL(leds_list_lock);
24
25 LIST_HEAD(leds_list);
26 EXPORT_SYMBOL_GPL(leds_list);
27
28 const char * const led_colors[LED_COLOR_ID_MAX] = {
29         [LED_COLOR_ID_WHITE] = "white",
30         [LED_COLOR_ID_RED] = "red",
31         [LED_COLOR_ID_GREEN] = "green",
32         [LED_COLOR_ID_BLUE] = "blue",
33         [LED_COLOR_ID_AMBER] = "amber",
34         [LED_COLOR_ID_VIOLET] = "violet",
35         [LED_COLOR_ID_YELLOW] = "yellow",
36         [LED_COLOR_ID_IR] = "ir",
37         [LED_COLOR_ID_MULTI] = "multicolor",
38         [LED_COLOR_ID_RGB] = "rgb",
39         [LED_COLOR_ID_PURPLE] = "purple",
40         [LED_COLOR_ID_ORANGE] = "orange",
41         [LED_COLOR_ID_PINK] = "pink",
42         [LED_COLOR_ID_CYAN] = "cyan",
43         [LED_COLOR_ID_LIME] = "lime",
44 };
45 EXPORT_SYMBOL_GPL(led_colors);
46
47 static int __led_set_brightness(struct led_classdev *led_cdev, unsigned int value)
48 {
49         if (!led_cdev->brightness_set)
50                 return -ENOTSUPP;
51
52         led_cdev->brightness_set(led_cdev, value);
53
54         return 0;
55 }
56
57 static int __led_set_brightness_blocking(struct led_classdev *led_cdev, unsigned int value)
58 {
59         if (!led_cdev->brightness_set_blocking)
60                 return -ENOTSUPP;
61
62         return led_cdev->brightness_set_blocking(led_cdev, value);
63 }
64
65 static void led_timer_function(struct timer_list *t)
66 {
67         struct led_classdev *led_cdev = from_timer(led_cdev, t, blink_timer);
68         unsigned long brightness;
69         unsigned long delay;
70
71         if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
72                 led_set_brightness_nosleep(led_cdev, LED_OFF);
73                 clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
74                 return;
75         }
76
77         if (test_and_clear_bit(LED_BLINK_ONESHOT_STOP,
78                                &led_cdev->work_flags)) {
79                 clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
80                 return;
81         }
82
83         brightness = led_get_brightness(led_cdev);
84         if (!brightness) {
85                 /* Time to switch the LED on. */
86                 if (test_and_clear_bit(LED_BLINK_BRIGHTNESS_CHANGE,
87                                         &led_cdev->work_flags))
88                         brightness = led_cdev->new_blink_brightness;
89                 else
90                         brightness = led_cdev->blink_brightness;
91                 delay = led_cdev->blink_delay_on;
92         } else {
93                 /* Store the current brightness value to be able
94                  * to restore it when the delay_off period is over.
95                  */
96                 led_cdev->blink_brightness = brightness;
97                 brightness = LED_OFF;
98                 delay = led_cdev->blink_delay_off;
99         }
100
101         led_set_brightness_nosleep(led_cdev, brightness);
102
103         /* Return in next iteration if led is in one-shot mode and we are in
104          * the final blink state so that the led is toggled each delay_on +
105          * delay_off milliseconds in worst case.
106          */
107         if (test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags)) {
108                 if (test_bit(LED_BLINK_INVERT, &led_cdev->work_flags)) {
109                         if (brightness)
110                                 set_bit(LED_BLINK_ONESHOT_STOP,
111                                         &led_cdev->work_flags);
112                 } else {
113                         if (!brightness)
114                                 set_bit(LED_BLINK_ONESHOT_STOP,
115                                         &led_cdev->work_flags);
116                 }
117         }
118
119         mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
120 }
121
122 static void set_brightness_delayed_set_brightness(struct led_classdev *led_cdev,
123                                                   unsigned int value)
124 {
125         int ret = 0;
126
127         ret = __led_set_brightness(led_cdev, value);
128         if (ret == -ENOTSUPP)
129                 ret = __led_set_brightness_blocking(led_cdev, value);
130         if (ret < 0 &&
131             /* LED HW might have been unplugged, therefore don't warn */
132             !(ret == -ENODEV && (led_cdev->flags & LED_UNREGISTERING) &&
133             (led_cdev->flags & LED_HW_PLUGGABLE)))
134                 dev_err(led_cdev->dev,
135                         "Setting an LED's brightness failed (%d)\n", ret);
136 }
137
138 static void set_brightness_delayed(struct work_struct *ws)
139 {
140         struct led_classdev *led_cdev =
141                 container_of(ws, struct led_classdev, set_brightness_work);
142
143         if (test_and_clear_bit(LED_BLINK_DISABLE, &led_cdev->work_flags)) {
144                 led_stop_software_blink(led_cdev);
145                 set_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags);
146         }
147
148         /*
149          * Triggers may call led_set_brightness(LED_OFF),
150          * led_set_brightness(LED_FULL) in quick succession to disable blinking
151          * and turn the LED on. Both actions may have been scheduled to run
152          * before this work item runs once. To make sure this works properly
153          * handle LED_SET_BRIGHTNESS_OFF first.
154          */
155         if (test_and_clear_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags))
156                 set_brightness_delayed_set_brightness(led_cdev, LED_OFF);
157
158         if (test_and_clear_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags))
159                 set_brightness_delayed_set_brightness(led_cdev, led_cdev->delayed_set_value);
160
161         if (test_and_clear_bit(LED_SET_BLINK, &led_cdev->work_flags)) {
162                 unsigned long delay_on = led_cdev->delayed_delay_on;
163                 unsigned long delay_off = led_cdev->delayed_delay_off;
164
165                 led_blink_set(led_cdev, &delay_on, &delay_off);
166         }
167 }
168
169 static void led_set_software_blink(struct led_classdev *led_cdev,
170                                    unsigned long delay_on,
171                                    unsigned long delay_off)
172 {
173         int current_brightness;
174
175         current_brightness = led_get_brightness(led_cdev);
176         if (current_brightness)
177                 led_cdev->blink_brightness = current_brightness;
178         if (!led_cdev->blink_brightness)
179                 led_cdev->blink_brightness = led_cdev->max_brightness;
180
181         led_cdev->blink_delay_on = delay_on;
182         led_cdev->blink_delay_off = delay_off;
183
184         /* never on - just set to off */
185         if (!delay_on) {
186                 led_set_brightness_nosleep(led_cdev, LED_OFF);
187                 return;
188         }
189
190         /* never off - just set to brightness */
191         if (!delay_off) {
192                 led_set_brightness_nosleep(led_cdev,
193                                            led_cdev->blink_brightness);
194                 return;
195         }
196
197         set_bit(LED_BLINK_SW, &led_cdev->work_flags);
198         mod_timer(&led_cdev->blink_timer, jiffies + 1);
199 }
200
201
202 static void led_blink_setup(struct led_classdev *led_cdev,
203                      unsigned long *delay_on,
204                      unsigned long *delay_off)
205 {
206         if (!test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags) &&
207             led_cdev->blink_set &&
208             !led_cdev->blink_set(led_cdev, delay_on, delay_off))
209                 return;
210
211         /* blink with 1 Hz as default if nothing specified */
212         if (!*delay_on && !*delay_off)
213                 *delay_on = *delay_off = 500;
214
215         led_set_software_blink(led_cdev, *delay_on, *delay_off);
216 }
217
218 void led_init_core(struct led_classdev *led_cdev)
219 {
220         INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
221
222         timer_setup(&led_cdev->blink_timer, led_timer_function, 0);
223 }
224 EXPORT_SYMBOL_GPL(led_init_core);
225
226 void led_blink_set(struct led_classdev *led_cdev,
227                    unsigned long *delay_on,
228                    unsigned long *delay_off)
229 {
230         del_timer_sync(&led_cdev->blink_timer);
231
232         clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
233         clear_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags);
234         clear_bit(LED_BLINK_ONESHOT_STOP, &led_cdev->work_flags);
235
236         led_blink_setup(led_cdev, delay_on, delay_off);
237 }
238 EXPORT_SYMBOL_GPL(led_blink_set);
239
240 void led_blink_set_oneshot(struct led_classdev *led_cdev,
241                            unsigned long *delay_on,
242                            unsigned long *delay_off,
243                            int invert)
244 {
245         if (test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags) &&
246              timer_pending(&led_cdev->blink_timer))
247                 return;
248
249         set_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags);
250         clear_bit(LED_BLINK_ONESHOT_STOP, &led_cdev->work_flags);
251
252         if (invert)
253                 set_bit(LED_BLINK_INVERT, &led_cdev->work_flags);
254         else
255                 clear_bit(LED_BLINK_INVERT, &led_cdev->work_flags);
256
257         led_blink_setup(led_cdev, delay_on, delay_off);
258 }
259 EXPORT_SYMBOL_GPL(led_blink_set_oneshot);
260
261 void led_blink_set_nosleep(struct led_classdev *led_cdev, unsigned long delay_on,
262                            unsigned long delay_off)
263 {
264         /* If necessary delegate to a work queue task. */
265         if (led_cdev->blink_set && led_cdev->brightness_set_blocking) {
266                 led_cdev->delayed_delay_on = delay_on;
267                 led_cdev->delayed_delay_off = delay_off;
268                 set_bit(LED_SET_BLINK, &led_cdev->work_flags);
269                 schedule_work(&led_cdev->set_brightness_work);
270                 return;
271         }
272
273         led_blink_set(led_cdev, &delay_on, &delay_off);
274 }
275 EXPORT_SYMBOL_GPL(led_blink_set_nosleep);
276
277 void led_stop_software_blink(struct led_classdev *led_cdev)
278 {
279         del_timer_sync(&led_cdev->blink_timer);
280         led_cdev->blink_delay_on = 0;
281         led_cdev->blink_delay_off = 0;
282         clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
283 }
284 EXPORT_SYMBOL_GPL(led_stop_software_blink);
285
286 void led_set_brightness(struct led_classdev *led_cdev, unsigned int brightness)
287 {
288         /*
289          * If software blink is active, delay brightness setting
290          * until the next timer tick.
291          */
292         if (test_bit(LED_BLINK_SW, &led_cdev->work_flags)) {
293                 /*
294                  * If we need to disable soft blinking delegate this to the
295                  * work queue task to avoid problems in case we are called
296                  * from hard irq context.
297                  */
298                 if (!brightness) {
299                         set_bit(LED_BLINK_DISABLE, &led_cdev->work_flags);
300                         schedule_work(&led_cdev->set_brightness_work);
301                 } else {
302                         set_bit(LED_BLINK_BRIGHTNESS_CHANGE,
303                                 &led_cdev->work_flags);
304                         led_cdev->new_blink_brightness = brightness;
305                 }
306                 return;
307         }
308
309         led_set_brightness_nosleep(led_cdev, brightness);
310 }
311 EXPORT_SYMBOL_GPL(led_set_brightness);
312
313 void led_set_brightness_nopm(struct led_classdev *led_cdev, unsigned int value)
314 {
315         /* Use brightness_set op if available, it is guaranteed not to sleep */
316         if (!__led_set_brightness(led_cdev, value))
317                 return;
318
319         /*
320          * Brightness setting can sleep, delegate it to a work queue task.
321          * value 0 / LED_OFF is special, since it also disables hw-blinking
322          * (sw-blink disable is handled in led_set_brightness()).
323          * To avoid a hw-blink-disable getting lost when a second brightness
324          * change is done immediately afterwards (before the work runs),
325          * it uses a separate work_flag.
326          */
327         if (value) {
328                 led_cdev->delayed_set_value = value;
329                 set_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags);
330         } else {
331                 clear_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags);
332                 clear_bit(LED_SET_BLINK, &led_cdev->work_flags);
333                 set_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags);
334         }
335
336         schedule_work(&led_cdev->set_brightness_work);
337 }
338 EXPORT_SYMBOL_GPL(led_set_brightness_nopm);
339
340 void led_set_brightness_nosleep(struct led_classdev *led_cdev, unsigned int value)
341 {
342         led_cdev->brightness = min(value, led_cdev->max_brightness);
343
344         if (led_cdev->flags & LED_SUSPENDED)
345                 return;
346
347         led_set_brightness_nopm(led_cdev, led_cdev->brightness);
348 }
349 EXPORT_SYMBOL_GPL(led_set_brightness_nosleep);
350
351 int led_set_brightness_sync(struct led_classdev *led_cdev, unsigned int value)
352 {
353         if (led_cdev->blink_delay_on || led_cdev->blink_delay_off)
354                 return -EBUSY;
355
356         led_cdev->brightness = min(value, led_cdev->max_brightness);
357
358         if (led_cdev->flags & LED_SUSPENDED)
359                 return 0;
360
361         return __led_set_brightness_blocking(led_cdev, led_cdev->brightness);
362 }
363 EXPORT_SYMBOL_GPL(led_set_brightness_sync);
364
365 int led_update_brightness(struct led_classdev *led_cdev)
366 {
367         int ret;
368
369         if (led_cdev->brightness_get) {
370                 ret = led_cdev->brightness_get(led_cdev);
371                 if (ret < 0)
372                         return ret;
373
374                 led_cdev->brightness = ret;
375         }
376
377         return 0;
378 }
379 EXPORT_SYMBOL_GPL(led_update_brightness);
380
381 u32 *led_get_default_pattern(struct led_classdev *led_cdev, unsigned int *size)
382 {
383         struct fwnode_handle *fwnode = led_cdev->dev->fwnode;
384         u32 *pattern;
385         int count;
386
387         count = fwnode_property_count_u32(fwnode, "led-pattern");
388         if (count < 0)
389                 return NULL;
390
391         pattern = kcalloc(count, sizeof(*pattern), GFP_KERNEL);
392         if (!pattern)
393                 return NULL;
394
395         if (fwnode_property_read_u32_array(fwnode, "led-pattern", pattern, count)) {
396                 kfree(pattern);
397                 return NULL;
398         }
399
400         *size = count;
401
402         return pattern;
403 }
404 EXPORT_SYMBOL_GPL(led_get_default_pattern);
405
406 /* Caller must ensure led_cdev->led_access held */
407 void led_sysfs_disable(struct led_classdev *led_cdev)
408 {
409         lockdep_assert_held(&led_cdev->led_access);
410
411         led_cdev->flags |= LED_SYSFS_DISABLE;
412 }
413 EXPORT_SYMBOL_GPL(led_sysfs_disable);
414
415 /* Caller must ensure led_cdev->led_access held */
416 void led_sysfs_enable(struct led_classdev *led_cdev)
417 {
418         lockdep_assert_held(&led_cdev->led_access);
419
420         led_cdev->flags &= ~LED_SYSFS_DISABLE;
421 }
422 EXPORT_SYMBOL_GPL(led_sysfs_enable);
423
424 static void led_parse_fwnode_props(struct device *dev,
425                                    struct fwnode_handle *fwnode,
426                                    struct led_properties *props)
427 {
428         int ret;
429
430         if (!fwnode)
431                 return;
432
433         if (fwnode_property_present(fwnode, "label")) {
434                 ret = fwnode_property_read_string(fwnode, "label", &props->label);
435                 if (ret)
436                         dev_err(dev, "Error parsing 'label' property (%d)\n", ret);
437                 return;
438         }
439
440         if (fwnode_property_present(fwnode, "color")) {
441                 ret = fwnode_property_read_u32(fwnode, "color", &props->color);
442                 if (ret)
443                         dev_err(dev, "Error parsing 'color' property (%d)\n", ret);
444                 else if (props->color >= LED_COLOR_ID_MAX)
445                         dev_err(dev, "LED color identifier out of range\n");
446                 else
447                         props->color_present = true;
448         }
449
450
451         if (!fwnode_property_present(fwnode, "function"))
452                 return;
453
454         ret = fwnode_property_read_string(fwnode, "function", &props->function);
455         if (ret) {
456                 dev_err(dev,
457                         "Error parsing 'function' property (%d)\n",
458                         ret);
459         }
460
461         if (!fwnode_property_present(fwnode, "function-enumerator"))
462                 return;
463
464         ret = fwnode_property_read_u32(fwnode, "function-enumerator",
465                                        &props->func_enum);
466         if (ret) {
467                 dev_err(dev,
468                         "Error parsing 'function-enumerator' property (%d)\n",
469                         ret);
470         } else {
471                 props->func_enum_present = true;
472         }
473 }
474
475 int led_compose_name(struct device *dev, struct led_init_data *init_data,
476                      char *led_classdev_name)
477 {
478         struct led_properties props = {};
479         struct fwnode_handle *fwnode = init_data->fwnode;
480         const char *devicename = init_data->devicename;
481
482         if (!led_classdev_name)
483                 return -EINVAL;
484
485         led_parse_fwnode_props(dev, fwnode, &props);
486
487         if (props.label) {
488                 /*
489                  * If init_data.devicename is NULL, then it indicates that
490                  * DT label should be used as-is for LED class device name.
491                  * Otherwise the label is prepended with devicename to compose
492                  * the final LED class device name.
493                  */
494                 if (!devicename) {
495                         strscpy(led_classdev_name, props.label,
496                                 LED_MAX_NAME_SIZE);
497                 } else {
498                         snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
499                                  devicename, props.label);
500                 }
501         } else if (props.function || props.color_present) {
502                 char tmp_buf[LED_MAX_NAME_SIZE];
503
504                 if (props.func_enum_present) {
505                         snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s-%d",
506                                  props.color_present ? led_colors[props.color] : "",
507                                  props.function ?: "", props.func_enum);
508                 } else {
509                         snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s",
510                                  props.color_present ? led_colors[props.color] : "",
511                                  props.function ?: "");
512                 }
513                 if (init_data->devname_mandatory) {
514                         snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
515                                  devicename, tmp_buf);
516                 } else {
517                         strscpy(led_classdev_name, tmp_buf, LED_MAX_NAME_SIZE);
518
519                 }
520         } else if (init_data->default_label) {
521                 if (!devicename) {
522                         dev_err(dev, "Legacy LED naming requires devicename segment");
523                         return -EINVAL;
524                 }
525                 snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
526                          devicename, init_data->default_label);
527         } else if (is_of_node(fwnode)) {
528                 strscpy(led_classdev_name, to_of_node(fwnode)->name,
529                         LED_MAX_NAME_SIZE);
530         } else
531                 return -EINVAL;
532
533         return 0;
534 }
535 EXPORT_SYMBOL_GPL(led_compose_name);
536
537 enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode)
538 {
539         const char *state = NULL;
540
541         if (!fwnode_property_read_string(fwnode, "default-state", &state)) {
542                 if (!strcmp(state, "keep"))
543                         return LEDS_DEFSTATE_KEEP;
544                 if (!strcmp(state, "on"))
545                         return LEDS_DEFSTATE_ON;
546         }
547
548         return LEDS_DEFSTATE_OFF;
549 }
550 EXPORT_SYMBOL_GPL(led_init_default_state_get);