led: Configure LED default-state on boot
authorMarek Vasut <marex@denx.de>
Sun, 3 Apr 2022 23:23:27 +0000 (01:23 +0200)
committerTom Rini <trini@konsulko.com>
Thu, 14 Apr 2022 19:39:15 +0000 (15:39 -0400)
In case the DT LED subnode contains "default-state" property set to
either "on" or "off", probe the LED driver and configure the LED state
automatically.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
Cc: Patrick Delaunay <patrick.delaunay@foss.st.com>
Cc: Philippe Reynes <philippe.reynes@softathome.com>
Cc: Sean Anderson <seanga2@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Steven Lawrance <steven.lawrance@softathome.com>
[trini: Update the relevant test now that we have support]
Signed-off-by: Tom Rini <trini@konsulko.com>
drivers/led/led-uclass.c
include/led.h
test/cmd/pinmux.c

index 2f4aa18..5d7bf40 100644 (file)
@@ -66,43 +66,49 @@ int led_set_period(struct udevice *dev, int period_ms)
 }
 #endif
 
+/* This is superseded by led_post_bind()/led_post_probe() below. */
 int led_default_state(void)
 {
-       struct udevice *dev;
-       struct uclass *uc;
-       const char *default_state;
-       int ret;
-
-       ret = uclass_get(UCLASS_LED, &uc);
-       if (ret)
-               return ret;
-       for (uclass_find_first_device(UCLASS_LED, &dev);
-            dev;
-            uclass_find_next_device(&dev)) {
-               default_state = dev_read_string(dev, "default-state");
-               if (!default_state)
-                       continue;
-               ret = device_probe(dev);
-               if (ret)
-                       return ret;
-               if (!strncmp(default_state, "on", 2))
-                       led_set_state(dev, LEDST_ON);
-               else if (!strncmp(default_state, "off", 3))
-                       led_set_state(dev, LEDST_OFF);
-               /* default-state = "keep" : device is only probed */
-       }
-
-       return ret;
+       return 0;
 }
 
 static int led_post_bind(struct udevice *dev)
 {
        struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+       const char *default_state;
 
        uc_plat->label = dev_read_string(dev, "label");
        if (!uc_plat->label)
                uc_plat->label = ofnode_get_name(dev_ofnode(dev));
 
+       uc_plat->default_state = LEDST_COUNT;
+
+       default_state = dev_read_string(dev, "default-state");
+       if (!default_state)
+               return 0;
+
+       if (!strncmp(default_state, "on", 2))
+               uc_plat->default_state = LEDST_ON;
+       else if (!strncmp(default_state, "off", 3))
+               uc_plat->default_state = LEDST_OFF;
+       else
+               return 0;
+
+       /*
+        * In case the LED has default-state DT property, trigger
+        * probe() to configure its default state during startup.
+        */
+       return device_probe(dev);
+}
+
+static int led_post_probe(struct udevice *dev)
+{
+       struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+       if (uc_plat->default_state == LEDST_ON ||
+           uc_plat->default_state == LEDST_OFF)
+               led_set_state(dev, uc_plat->default_state);
+
        return 0;
 }
 
@@ -111,4 +117,5 @@ UCLASS_DRIVER(led) = {
        .name           = "led",
        .per_device_plat_auto   = sizeof(struct led_uc_plat),
        .post_bind      = led_post_bind,
+       .post_probe     = led_post_probe,
 };
index 8eeb5a7..43acca8 100644 (file)
@@ -9,13 +9,26 @@
 
 struct udevice;
 
+enum led_state_t {
+       LEDST_OFF = 0,
+       LEDST_ON = 1,
+       LEDST_TOGGLE,
+#ifdef CONFIG_LED_BLINK
+       LEDST_BLINK,
+#endif
+
+       LEDST_COUNT,
+};
+
 /**
  * struct led_uc_plat - Platform data the uclass stores about each device
  *
  * @label:     LED label
+ * @default_state:     LED default state
  */
 struct led_uc_plat {
        const char *label;
+       enum led_state_t default_state;
 };
 
 /**
@@ -27,17 +40,6 @@ struct led_uc_priv {
        int period_ms;
 };
 
-enum led_state_t {
-       LEDST_OFF = 0,
-       LEDST_ON = 1,
-       LEDST_TOGGLE,
-#ifdef CONFIG_LED_BLINK
-       LEDST_BLINK,
-#endif
-
-       LEDST_COUNT,
-};
-
 struct led_ops {
        /**
         * set_state() - set the state of an LED
index ba338b8..de3bb0d 100644 (file)
@@ -16,7 +16,7 @@ static int dm_test_cmd_pinmux_status_pinname(struct unit_test_state *uts)
        /* Test that 'pinmux status <pinname>' displays the selected pin. */
        console_record_reset();
        run_command("pinmux status a5", 0);
-       ut_assert_nextlinen("a5        : gpio input .");
+       ut_assert_nextlinen("a5        : gpio output .");
        ut_assert_console_end();
 
        console_record_reset();