[U-Boot] [PATCH v4 0/5] dm: led: remove auto probe in binding function

Hi,
The commit bc882f5d5c7b4d6ed5e927bf838863af43c786e7 introduce auto probe of LED in binding function but that cause issue on my board.
This first patch of this patchset activateis the LED on my board to explain the issue, the second patch revert this commit and the third one propose an other solution.
For me, this commit is a error because in README of doc/driver-model/ it is indicated:
The device's bind() method is permitted to perform simple actions, but should not scan the device tree node, not initialise hardware, nor set up structures or allocate memory. All of these tasks should be left for the probe() method.
And in the patch the LED driver is probed during the binding scan.
When I activated the LED in my ARM target with the patch "stm32mp1: add gpio led support", I have the sequence:
dm_init_and_scan() :
1/ dm_scan_fdt_node() => loop on all the node
2/ scan for LED node => probe of LED driver is forced by "default-state" detection LED1 - "red" => probe of father of "red" node A - led B - soc C - root => probe of node needed by GPIO 1 - pin-controller 2 - gpio@50002000 3 - rcc-clk@50000000 4 - rcc@50000000
=> probe forced by default state for other led LED2 - green LED3 - orange
=> probe of node needed by GPIO (other bank) 5 - gpio@50009000
3/ dm_extended_scan_fdt scan continue... scan node "fixed-clock" under "/clocks" clk-hse clk-hsi clk-lse clk-lsi clk-csi
4/ probe of all the used devices.... after dm_extended_scan_fdt()
So many driver are probed before the end of the scan binding loop !
And that cause issue in my board (boot failed) because the rcc-clk clock driver found the input frequency with these fixed-clock, which are binded only after the stm32mp1 clock driver probe.
For me probe in forbidden in binding function and thus uclass_get_device_tail() is not allowed in the commit bc882f5d5c7b4d6ed5e927bf838863af43c786e7 which need to be reverted.
In the third patch I proposed an other solution based on the existing solution in u-class regulator used to enable regulator with "boot on" property (see regulators_enable_boot_on function).
I think that adding a function is the better solution in the driver model to force probe for some node according binding information (after dm_init_and_scan call).
This new function should be called in board_init function for each board but it could be also added in init_sequence_r[] in future.
Changes in v4: - simplify the uclass impact after Patrick Bruenn review - remove #ifdef CONFIG_LED for sandbox
Changes in v3: - add motivation in revert commit - minor update after Simon review - include led.h to avoid compilation warning on stm32mp1 board
Changes in v2: - add sandbox impact and test update
Patrick Delaunay (5): stm32mp1: add gpio led support Revert "dm: led: auto probe() LEDs with "default-state"" dm: led: move default state support in led uclass stm32mp1: use new function led default state sandbox: led: use new function to configure default state
arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi | 24 ++++++++++++++++++++++++ board/sandbox/sandbox.c | 9 +++++++++ board/st/stm32mp1/stm32mp1.c | 4 ++++ common/board_r.c | 3 ++- configs/stm32mp15_basic_defconfig | 2 ++ drivers/led/led-uclass.c | 30 ++++++++++++++++++++++++++++++ drivers/led/led_gpio.c | 17 ----------------- include/led.h | 9 +++++++++ test/dm/led.c | 3 +++ 9 files changed, 83 insertions(+), 18 deletions(-)

This patch add the 4 LED available on the ED1 board and activated gpio led driver.
Reviewed-by: Simon Glass sjg@chromium.org Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
Changes in v4: None Changes in v3: None Changes in v2: None
arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi | 24 ++++++++++++++++++++++++ configs/stm32mp15_basic_defconfig | 2 ++ 2 files changed, 26 insertions(+)
diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi index 39a0ebc..4898483 100644 --- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi @@ -13,6 +13,30 @@ mmc1 = &sdmmc2; i2c3 = &i2c4; }; + + led { + compatible = "gpio-leds"; + + red { + label = "stm32mp:red:status"; + gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + green { + label = "stm32mp:green:user"; + gpios = <&gpioa 14 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + orange { + label = "stm32mp:orange:status"; + gpios = <&gpioh 7 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + blue { + label = "stm32mp:blue:user"; + gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; + }; + }; };
&uart4_pins_a { diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index c72a440..2cac114 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -29,6 +29,8 @@ CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set CONFIG_DM_I2C=y CONFIG_SYS_I2C_STM32F7=y +CONFIG_LED=y +CONFIG_LED_GPIO=y CONFIG_DM_MMC=y CONFIG_STM32_SDMMC2=y # CONFIG_PINCTRL_FULL is not set

On Fri, Jul 27, 2018 at 04:37:05PM +0200, Patrick Delaunay wrote:
This patch add the 4 LED available on the ED1 board and activated gpio led driver.
Reviewed-by: Simon Glass sjg@chromium.org Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot/master, thanks!

This reverts commit bc882f5d5c7b4d6ed5e927bf838863af43c786e7. because this patch adds the probe of LED driver during the binding phasis. It is not allowed in driver model because the drivers (clock, pincontrol) needed by the LED driver can be also probed before the binding of all the device and it is a source of problems.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
Changes in v4: None Changes in v3: - add motivation in revert commit
Changes in v2: None
drivers/led/led_gpio.c | 9 --------- 1 file changed, 9 deletions(-)
diff --git a/drivers/led/led_gpio.c b/drivers/led/led_gpio.c index a36942b..533587d 100644 --- a/drivers/led/led_gpio.c +++ b/drivers/led/led_gpio.c @@ -10,7 +10,6 @@ #include <led.h> #include <asm/gpio.h> #include <dm/lists.h> -#include <dm/uclass-internal.h>
struct led_gpio_priv { struct gpio_desc gpio; @@ -118,14 +117,6 @@ static int led_gpio_bind(struct udevice *parent) return ret; uc_plat = dev_get_uclass_platdata(dev); uc_plat->label = label; - - if (ofnode_read_bool(node, "default-state")) { - struct udevice *devp; - - ret = uclass_get_device_tail(dev, 0, &devp); - if (ret) - return ret; - } }
return 0;

On Fri, Jul 27, 2018 at 04:37:06PM +0200, Patrick Delaunay wrote:
This reverts commit bc882f5d5c7b4d6ed5e927bf838863af43c786e7. because this patch adds the probe of LED driver during the binding phasis. It is not allowed in driver model because the drivers (clock, pincontrol) needed by the LED driver can be also probed before the binding of all the device and it is a source of problems.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot/master, thanks!

This patch save common LED property "default-state" value in post bind of LED uclass. The configuration for this default state is only performed when led_default_state() is called; It can be called in your board_init() or it could added in init_sequence_r[] in future.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
Changes in v4: - simplify the uclass impact after Patrick Bruenn review
Changes in v3: None Changes in v2: None
drivers/led/led-uclass.c | 30 ++++++++++++++++++++++++++++++ drivers/led/led_gpio.c | 8 -------- include/led.h | 9 +++++++++ 3 files changed, 39 insertions(+), 8 deletions(-)
diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c index 2f4d69e..2859475 100644 --- a/drivers/led/led-uclass.c +++ b/drivers/led/led-uclass.c @@ -8,6 +8,7 @@ #include <dm.h> #include <errno.h> #include <led.h> +#include <dm/device-internal.h> #include <dm/root.h> #include <dm/uclass-internal.h>
@@ -63,6 +64,35 @@ int led_set_period(struct udevice *dev, int period_ms) } #endif
+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; +} + UCLASS_DRIVER(led) = { .id = UCLASS_LED, .name = "led", diff --git a/drivers/led/led_gpio.c b/drivers/led/led_gpio.c index 533587d..93f6b91 100644 --- a/drivers/led/led_gpio.c +++ b/drivers/led/led_gpio.c @@ -57,7 +57,6 @@ static int led_gpio_probe(struct udevice *dev) { struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev); struct led_gpio_priv *priv = dev_get_priv(dev); - const char *default_state; int ret;
/* Ignore the top-level LED node */ @@ -68,13 +67,6 @@ static int led_gpio_probe(struct udevice *dev) if (ret) return ret;
- default_state = dev_read_string(dev, "default-state"); - if (default_state) { - if (!strncmp(default_state, "on", 2)) - gpio_led_set_state(dev, LEDST_ON); - else if (!strncmp(default_state, "off", 3)) - gpio_led_set_state(dev, LEDST_OFF); - } return 0; }
diff --git a/include/led.h b/include/led.h index 940b97f..7bfdddf 100644 --- a/include/led.h +++ b/include/led.h @@ -106,4 +106,13 @@ enum led_state_t led_get_state(struct udevice *dev); */ int led_set_period(struct udevice *dev, int period_ms);
+/** + * led_default_state() - set the default state for all the LED + * + * This enables all leds which have default state. + * see Documentation/devicetree/bindings/leds/common.txt + * + */ +int led_default_state(void); + #endif

On Fri, Jul 27, 2018 at 04:37:07PM +0200, Patrick Delaunay wrote:
This patch save common LED property "default-state" value in post bind of LED uclass. The configuration for this default state is only performed when led_default_state() is called; It can be called in your board_init() or it could added in init_sequence_r[] in future.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot/master, thanks!

Initialize the led with the default state defined in device tree.
Reviewed-by: Simon Glass sjg@chromium.org
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
Changes in v4: None Changes in v3: - minor update after Simon review - include led.h to avoid compilation warning on stm32mp1 board
Changes in v2: None
board/st/stm32mp1/stm32mp1.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index cc39fa6..bfc8ab6 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -4,6 +4,7 @@ */ #include <config.h> #include <common.h> +#include <led.h> #include <asm/arch/stm32.h>
/* @@ -22,5 +23,8 @@ int board_init(void) /* address of boot parameters */ gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100;
+ if (IS_ENABLED(CONFIG_LED)) + led_default_state(); + return 0; }

On Fri, Jul 27, 2018 at 04:37:08PM +0200, Patrick Delaunay wrote:
Initialize the led with the default state defined in device tree.
Reviewed-by: Simon Glass sjg@chromium.org
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot/master, thanks!

Initialize the led with the default state defined in device tree in board_init and solve issue with test for led default state.
Reviewed-by: Simon Glass sjg@chromium.org
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com --- Led default-state is correctly handle in Sandbox, tested with: ./u-boot -d ./arch/sandbox/dts/test.dtb => led list sandbox:red <inactive> sandbox:green <inactive> sandbox:default_on on sandbox:default_off off
This patch solve "make tests" issue introduced by http://patchwork.ozlabs.org/patch/943651/
Changes in v4: - remove #ifdef CONFIG_LED for sandbox
Changes in v3: None Changes in v2: - add sandbox impact and test update
board/sandbox/sandbox.c | 9 +++++++++ common/board_r.c | 3 ++- test/dm/led.c | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c index 195f620..0e87674 100644 --- a/board/sandbox/sandbox.c +++ b/board/sandbox/sandbox.c @@ -6,6 +6,7 @@ #include <common.h> #include <cros_ec.h> #include <dm.h> +#include <led.h> #include <os.h> #include <asm/test.h> #include <asm/u-boot-sandbox.h> @@ -47,6 +48,14 @@ int dram_init(void) return 0; }
+int board_init(void) +{ + if (IS_ENABLED(CONFIG_LED)) + led_default_state(); + + return 0; +} + #ifdef CONFIG_BOARD_LATE_INIT int board_late_init(void) { diff --git a/common/board_r.c b/common/board_r.c index 64f2574..9402c0e 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -690,7 +690,8 @@ static init_fnc_t init_sequence_r[] = { #ifdef CONFIG_DM initr_dm, #endif -#if defined(CONFIG_ARM) || defined(CONFIG_NDS32) || defined(CONFIG_RISCV) +#if defined(CONFIG_ARM) || defined(CONFIG_NDS32) || defined(CONFIG_RISCV) || \ + defined(CONFIG_SANDBOX) board_init, /* Setup chipselects */ #endif /* diff --git a/test/dm/led.c b/test/dm/led.c index 0071f21..00de7b3 100644 --- a/test/dm/led.c +++ b/test/dm/led.c @@ -32,6 +32,9 @@ static int dm_test_led_default_state(struct unit_test_state *uts) { struct udevice *dev;
+ /* configure the default state (auto-probe) */ + led_default_state(); + /* Check that we handle the default-state property correctly. */ ut_assertok(led_get_by_label("sandbox:default_on", &dev)); ut_asserteq(LEDST_ON, led_get_state(dev));

On Fri, Jul 27, 2018 at 04:37:09PM +0200, Patrick Delaunay wrote:
Initialize the led with the default state defined in device tree in board_init and solve issue with test for led default state.
Reviewed-by: Simon Glass sjg@chromium.org
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot/master, thanks!
participants (2)
-
Patrick Delaunay
-
Tom Rini