summaryrefslogtreecommitdiffstats
path: root/drivers/led
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2017-03-13 10:33:39 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2017-03-30 08:23:20 +0200
commit7dd8ae82311daa9ee22ffc762ea158c3977fb20c (patch)
treea4730bd86f490b0f02b1fa5cccc242923357a995 /drivers/led
parentebc5ed5310b2aadbd6b1f1d914dce8639b759a7d (diff)
downloadbarebox-7dd8ae82311daa9ee22ffc762ea158c3977fb20c.tar.gz
barebox-7dd8ae82311daa9ee22ffc762ea158c3977fb20c.tar.xz
led-trigger: Allow multiple led triggers of the same type
We used to have a static array of trigger types which, allows only one led per trigger. While this is enough for panic and heartbeat, it falls short when multiple leds are associated to the default-on trigger. The default-on trigger is used to turn on a led statically from devicetree and may be used multiple times. This patch reworks the led triggers so that a trigger struct is allocated dynamically when needed and put onto a list. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/led')
-rw-r--r--drivers/led/led-triggers.c125
1 files changed, 97 insertions, 28 deletions
diff --git a/drivers/led/led-triggers.c b/drivers/led/led-triggers.c
index 6c05cc5bbf..76a1481e14 100644
--- a/drivers/led/led-triggers.c
+++ b/drivers/led/led-triggers.c
@@ -52,7 +52,7 @@ struct led_trigger_struct {
enum led_trigger trigger;
};
-static struct led_trigger_struct triggers[LED_TRIGGER_MAX];
+static LIST_HEAD(led_triggers);
/**
* led_trigger - triggers a trigger
@@ -63,17 +63,53 @@ static struct led_trigger_struct triggers[LED_TRIGGER_MAX];
*/
void led_trigger(enum led_trigger trigger, enum trigger_type type)
{
+ struct led_trigger_struct *led_trigger;
+
if (trigger >= LED_TRIGGER_MAX)
return;
- if (!triggers[trigger].led)
- return;
- if (type == TRIGGER_FLASH) {
- led_flash(triggers[trigger].led, 200);
- return;
+ list_for_each_entry(led_trigger, &led_triggers, list) {
+ if (led_trigger->trigger != trigger)
+ continue;
+
+ switch (type) {
+ case TRIGGER_FLASH:
+ led_flash(led_trigger->led, 200);
+ break;
+ case TRIGGER_ENABLE:
+ led_set(led_trigger->led, led_trigger->led->max_value);
+ break;
+ case TRIGGER_DISABLE:
+ led_set(led_trigger->led, 0);
+ break;
+ }
}
+}
+
+static struct led_trigger_struct *led_find_trigger(struct led *led)
+{
+ struct led_trigger_struct *led_trigger;
+
+ list_for_each_entry(led_trigger, &led_triggers, list)
+ if (led_trigger->led == led)
+ return led_trigger;
+
+ return NULL;
+}
- led_set(triggers[trigger].led, type == TRIGGER_ENABLE ? triggers[trigger].led->max_value : 0);
+void led_trigger_disable(struct led *led)
+{
+ struct led_trigger_struct *led_trigger;
+
+ led_trigger = led_find_trigger(led);
+ if (!led_trigger)
+ return;
+
+ list_del(&led_trigger->list);
+
+ led_set(led, 0);
+
+ free(led_trigger);
}
/**
@@ -86,40 +122,73 @@ void led_trigger(enum led_trigger trigger, enum trigger_type type)
*/
int led_set_trigger(enum led_trigger trigger, struct led *led)
{
- int i;
+ struct led_trigger_struct *led_trigger;
if (trigger >= LED_TRIGGER_MAX)
return -EINVAL;
- if (led)
- for (i = 0; i < LED_TRIGGER_MAX; i++)
- if (triggers[i].led == led)
- return -EBUSY;
+ led_trigger_disable(led);
- if (triggers[trigger].led && !led)
- led_set(triggers[trigger].led, 0);
+ led_trigger = xzalloc(sizeof(*led_trigger));
- triggers[trigger].led = led;
+ led_trigger->led = led;
+ led_trigger->trigger = trigger;
+ list_add_tail(&led_trigger->list, &led_triggers);
- if (led && trigger == LED_TRIGGER_DEFAULT_ON)
- led_set(triggers[trigger].led, triggers[trigger].led->max_value);
- if (led && trigger == LED_TRIGGER_HEARTBEAT)
+ if (trigger == LED_TRIGGER_DEFAULT_ON)
+ led_set(led, led->max_value);
+ if (trigger == LED_TRIGGER_HEARTBEAT)
led_blink(led, 200, 1000);
return 0;
}
+static char *trigger_names[] = {
+ [LED_TRIGGER_PANIC] = "panic",
+ [LED_TRIGGER_HEARTBEAT] = "heartbeat",
+ [LED_TRIGGER_NET_RX] = "net-rx",
+ [LED_TRIGGER_NET_TX] = "net-tx",
+ [LED_TRIGGER_NET_TXRX] = "net",
+ [LED_TRIGGER_DEFAULT_ON] = "default-on",
+};
+
+const char *trigger_name(enum led_trigger trigger)
+{
+ return trigger_names[trigger];
+}
+
+enum led_trigger trigger_by_name(const char *name)
+{
+ int i;
+
+ for (i = 0; i < LED_TRIGGER_MAX; i++)
+ if (!strcmp(name, trigger_names[i]))
+ return i;
+
+ return LED_TRIGGER_MAX;
+}
+
/**
- * led_get_trigger - get the LED for a trigger
- * @param trigger The trigger to set a LED for
- *
- * return the LED number of a trigger.
+ * led_triggers_show_info - Show information about all registered
+ * triggers
*/
-int led_get_trigger(enum led_trigger trigger)
+void led_triggers_show_info(void)
{
- if (trigger >= LED_TRIGGER_MAX)
- return -EINVAL;
- if (!triggers[trigger].led)
- return -ENODEV;
- return led_get_number(triggers[trigger].led);
+ struct led_trigger_struct *led_trigger;
+ int i;
+
+ for (i = 0; i < LED_TRIGGER_MAX; i++) {
+ printf("%s", trigger_name(i));
+
+ list_for_each_entry(led_trigger, &led_triggers, list) {
+ struct led *led = led_trigger->led;
+
+ if (led_trigger->trigger != i)
+ continue;
+
+ printf("\n LED %d (%s)", led->num, led->name);
+ }
+
+ printf("\n");
+ }
}