led: Configure LED default-state on boot

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>
diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c
index 2f4aa18..5d7bf40 100644
--- a/drivers/led/led-uclass.c
+++ b/drivers/led/led-uclass.c
@@ -66,43 +66,49 @@
 }
 #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 @@
 	.name		= "led",
 	.per_device_plat_auto	= sizeof(struct led_uc_plat),
 	.post_bind	= led_post_bind,
+	.post_probe	= led_post_probe,
 };
diff --git a/include/led.h b/include/led.h
index 8eeb5a7..43acca8 100644
--- a/include/led.h
+++ b/include/led.h
@@ -9,24 +9,6 @@
 
 struct udevice;
 
-/**
- * struct led_uc_plat - Platform data the uclass stores about each device
- *
- * @label:	LED label
- */
-struct led_uc_plat {
-	const char *label;
-};
-
-/**
- * struct led_uc_priv - Private data the uclass stores about each device
- *
- * @period_ms:	Flash period in milliseconds
- */
-struct led_uc_priv {
-	int period_ms;
-};
-
 enum led_state_t {
 	LEDST_OFF = 0,
 	LEDST_ON = 1,
@@ -38,6 +20,26 @@
 	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;
+};
+
+/**
+ * struct led_uc_priv - Private data the uclass stores about each device
+ *
+ * @period_ms:	Flash period in milliseconds
+ */
+struct led_uc_priv {
+	int period_ms;
+};
+
 struct led_ops {
 	/**
 	 * set_state() - set the state of an LED
diff --git a/test/cmd/pinmux.c b/test/cmd/pinmux.c
index ba338b8..de3bb0d 100644
--- a/test/cmd/pinmux.c
+++ b/test/cmd/pinmux.c
@@ -16,7 +16,7 @@
 	/* 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();