Re: [U-Boot] [PATCH v1 3/3] cmd: usb gadget: Add a command to bind a USB gadget driver to a UDC port

2018-06-14 Thread Stephen Warren

On 06/14/2018 09:11 AM, Simon Glass wrote:

On 14 June 2018 at 09:02, Jean-Jacques Hiblot  wrote:




On 13/06/2018 03:29, Simon Glass wrote:


Hi Jean-Jacques,

On 12 June 2018 at 03:31, Jean-Jacques Hiblot  wrote:


Hi,


On 08/06/2018 23:59, Simon Glass wrote:


Hi,

On 7 June 2018 at 01:39, Lukasz Majewski  wrote:


Hi Jean-Jacques,


Most of the time the UDC is bound to a driver when a dedicated
command is executed, like 'dfu'. But the ethernet gadget driver must
be bound by calling usb_ether_init() in the code otherwise the USB
ethernet adapter is not visible to the ethernet core.

In DM context, the platform code should not be used to bind UDC to a
particular driver, so adding a new command to bind a USB device port
to a driver.

usage example:
usbdev bind 0 usb_ether
usbdev unbind 0


I would prefer a comment from Simon (so adding him to CC) - as it looks
to me that we shall try to use DM to avoid adding separate commands for
binding.


We could perhaps introduce 'bind' and 'unbind' commands with similar
arguments?


What kind of parameters should be used to identify the device to bind ?
I see 2 possible options:
- node paths: bind /opc/omap_dwc3@4838/usb@483d usb_ether
- device class + index: bind usb_dev 0 usb_ether.

The last one looks a lot like what I proposed, only more generic, but
requires creating a table to match a string with a UCLASS id.
The first is more precise but IMO less user friendly.


We can look up a uclass by name, so your second open should work OK.
It matches the current U-Boot approach pretty well two since most
commands work this way.

However, I have sometimes thought (with driver model) of supporting
the first option as a fallback.

You could in fact have a function that supports both:

1. Option 1 - it does a global search for a device with that DT node
2. Option 2 - it does a uclass_get_device_by_seq() call

I agree that option 2 is likely to be much preferred in normal use.


I've been working on this and have come up with a slightly different interface:

bind  
unbind 
bind   
unbind  


Interface with node path:
It is a symmetric interface:
example:
bind /ocp/ocp2scp@483e8000 generic_simple_bus
unbind /ocp/ocp2scp@483e8000


Interface with class/index:
This is by essence an asymmetric interface: the class/index pair is not the 
same for binding as for unbinding
example:
bind usb_dev_generic 0 usb_ether
unbind eth 1

While it makes sense, it may be a bit harder to use because of the asymmetry


That seems OK to me. I added some more people for comment. Please add
anyone else you can think of who might have ideas.


Why wouldn't the unbind arguments always match the bind arguments:

bind /ocp/ocp2scp@483e8000 generic_simple_bus
unbind /ocp/ocp2scp@483e8000

bind usb_dev_generic 0 usb_ether
unbind usb_dev_generic 0 usb_ether

One benefit here is that it's completely symmetric, so easier to specify 
and understand. Also, one might imagine a future where we could do:


bind usb_dev_generic 0 usb_ether
bind usb_dev_generic 0 usb_acm
# Here, can use both Ethernet and serial (console) over this port
unbind usb_dev_generic 0 usb_acm
unbind usb_dev_generic 0 usb_ether

(Although perhaps in this case, should we actually be binding not 
usb_ether and usb_acm directly, but rather binding usb_gadget, and 
somehow configuring what protocols usb_gadget exposes separately 
beforehand? For example, see how the kernel's USB gadget sysfs control 
works.)

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 3/3] cmd: usb gadget: Add a command to bind a USB gadget driver to a UDC port

2018-06-14 Thread Simon Glass
On 14 June 2018 at 09:02, Jean-Jacques Hiblot  wrote:
>
>
>
> On 13/06/2018 03:29, Simon Glass wrote:
>>
>> Hi Jean-Jacques,
>>
>> On 12 June 2018 at 03:31, Jean-Jacques Hiblot  wrote:
>>>
>>> Hi,
>>>
>>>
>>> On 08/06/2018 23:59, Simon Glass wrote:

 Hi,

 On 7 June 2018 at 01:39, Lukasz Majewski  wrote:
>
> Hi Jean-Jacques,
>
>> Most of the time the UDC is bound to a driver when a dedicated
>> command is executed, like 'dfu'. But the ethernet gadget driver must
>> be bound by calling usb_ether_init() in the code otherwise the USB
>> ethernet adapter is not visible to the ethernet core.
>>
>> In DM context, the platform code should not be used to bind UDC to a
>> particular driver, so adding a new command to bind a USB device port
>> to a driver.
>>
>> usage example:
>> usbdev bind 0 usb_ether
>> usbdev unbind 0
>
> I would prefer a comment from Simon (so adding him to CC) - as it looks
> to me that we shall try to use DM to avoid adding separate commands for
> binding.

 We could perhaps introduce 'bind' and 'unbind' commands with similar
 arguments?
>>>
>>> What kind of parameters should be used to identify the device to bind ?
>>> I see 2 possible options:
>>> - node paths: bind /opc/omap_dwc3@4838/usb@483d usb_ether
>>> - device class + index: bind usb_dev 0 usb_ether.
>>>
>>> The last one looks a lot like what I proposed, only more generic, but
>>> requires creating a table to match a string with a UCLASS id.
>>> The first is more precise but IMO less user friendly.
>>
>> We can look up a uclass by name, so your second open should work OK.
>> It matches the current U-Boot approach pretty well two since most
>> commands work this way.
>>
>> However, I have sometimes thought (with driver model) of supporting
>> the first option as a fallback.
>>
>> You could in fact have a function that supports both:
>>
>> 1. Option 1 - it does a global search for a device with that DT node
>> 2. Option 2 - it does a uclass_get_device_by_seq() call
>>
>> I agree that option 2 is likely to be much preferred in normal use.
>
> I've been working on this and have come up with a slightly different 
> interface:
>
> bind  
> unbind 
> bind   
> unbind  
>
>
> Interface with node path:
> It is a symmetric interface:
> example:
> bind /ocp/ocp2scp@483e8000 generic_simple_bus
> unbind /ocp/ocp2scp@483e8000
>
>
> Interface with class/index:
> This is by essence an asymmetric interface: the class/index pair is not the 
> same for binding as for unbinding
> example:
> bind usb_dev_generic 0 usb_ether
> unbind eth 1
>
> While it makes sense, it may be a bit harder to use because of the asymmetry

That seems OK to me. I added some more people for comment. Please add
anyone else you can think of who might have ideas.

Regards,
Simon
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 3/3] cmd: usb gadget: Add a command to bind a USB gadget driver to a UDC port

2018-06-14 Thread Jean-Jacques Hiblot



On 13/06/2018 03:29, Simon Glass wrote:

Hi Jean-Jacques,

On 12 June 2018 at 03:31, Jean-Jacques Hiblot  wrote:

Hi,


On 08/06/2018 23:59, Simon Glass wrote:

Hi,

On 7 June 2018 at 01:39, Lukasz Majewski  wrote:

Hi Jean-Jacques,


Most of the time the UDC is bound to a driver when a dedicated
command is executed, like 'dfu'. But the ethernet gadget driver must
be bound by calling usb_ether_init() in the code otherwise the USB
ethernet adapter is not visible to the ethernet core.

In DM context, the platform code should not be used to bind UDC to a
particular driver, so adding a new command to bind a USB device port
to a driver.

usage example:
usbdev bind 0 usb_ether
usbdev unbind 0

I would prefer a comment from Simon (so adding him to CC) - as it looks
to me that we shall try to use DM to avoid adding separate commands for
binding.

We could perhaps introduce 'bind' and 'unbind' commands with similar
arguments?

What kind of parameters should be used to identify the device to bind ?
I see 2 possible options:
- node paths: bind /opc/omap_dwc3@4838/usb@483d usb_ether
- device class + index: bind usb_dev 0 usb_ether.

The last one looks a lot like what I proposed, only more generic, but
requires creating a table to match a string with a UCLASS id.
The first is more precise but IMO less user friendly.

We can look up a uclass by name, so your second open should work OK.
It matches the current U-Boot approach pretty well two since most
commands work this way.

However, I have sometimes thought (with driver model) of supporting
the first option as a fallback.

You could in fact have a function that supports both:

1. Option 1 - it does a global search for a device with that DT node
2. Option 2 - it does a uclass_get_device_by_seq() call

I agree that option 2 is likely to be much preferred in normal use.
I've been working on this and have come up with a slightly different 
interface:


bind  
unbind 
bind   
unbind  


Interface with node path:
It is a symmetric interface:
example:
bind /ocp/ocp2scp@483e8000 generic_simple_bus
unbind /ocp/ocp2scp@483e8000


Interface with class/index:
This is by essence an asymmetric interface: the class/index pair is not 
the same for binding as for unbinding

example:
bind usb_dev_generic 0 usb_ether
unbind eth 1

While it makes sense, it may be a bit harder to use because of the asymmetry

JJ



Regards,
Simon



___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 3/3] cmd: usb gadget: Add a command to bind a USB gadget driver to a UDC port

2018-06-12 Thread Simon Glass
Hi Jean-Jacques,

On 12 June 2018 at 03:31, Jean-Jacques Hiblot  wrote:
> Hi,
>
>
> On 08/06/2018 23:59, Simon Glass wrote:
>>
>> Hi,
>>
>> On 7 June 2018 at 01:39, Lukasz Majewski  wrote:
>>>
>>> Hi Jean-Jacques,
>>>
 Most of the time the UDC is bound to a driver when a dedicated
 command is executed, like 'dfu'. But the ethernet gadget driver must
 be bound by calling usb_ether_init() in the code otherwise the USB
 ethernet adapter is not visible to the ethernet core.

 In DM context, the platform code should not be used to bind UDC to a
 particular driver, so adding a new command to bind a USB device port
 to a driver.

 usage example:
 usbdev bind 0 usb_ether
 usbdev unbind 0
>>>
>>> I would prefer a comment from Simon (so adding him to CC) - as it looks
>>> to me that we shall try to use DM to avoid adding separate commands for
>>> binding.
>>
>> We could perhaps introduce 'bind' and 'unbind' commands with similar
>> arguments?
>
> What kind of parameters should be used to identify the device to bind ?
> I see 2 possible options:
> - node paths: bind /opc/omap_dwc3@4838/usb@483d usb_ether
> - device class + index: bind usb_dev 0 usb_ether.
>
> The last one looks a lot like what I proposed, only more generic, but
> requires creating a table to match a string with a UCLASS id.
> The first is more precise but IMO less user friendly.

We can look up a uclass by name, so your second open should work OK.
It matches the current U-Boot approach pretty well two since most
commands work this way.

However, I have sometimes thought (with driver model) of supporting
the first option as a fallback.

You could in fact have a function that supports both:

1. Option 1 - it does a global search for a device with that DT node
2. Option 2 - it does a uclass_get_device_by_seq() call

I agree that option 2 is likely to be much preferred in normal use.

Regards,
Simon
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 3/3] cmd: usb gadget: Add a command to bind a USB gadget driver to a UDC port

2018-06-12 Thread Jean-Jacques Hiblot

Hi,


On 08/06/2018 23:59, Simon Glass wrote:

Hi,

On 7 June 2018 at 01:39, Lukasz Majewski  wrote:

Hi Jean-Jacques,


Most of the time the UDC is bound to a driver when a dedicated
command is executed, like 'dfu'. But the ethernet gadget driver must
be bound by calling usb_ether_init() in the code otherwise the USB
ethernet adapter is not visible to the ethernet core.

In DM context, the platform code should not be used to bind UDC to a
particular driver, so adding a new command to bind a USB device port
to a driver.

usage example:
usbdev bind 0 usb_ether
usbdev unbind 0

I would prefer a comment from Simon (so adding him to CC) - as it looks
to me that we shall try to use DM to avoid adding separate commands for
binding.

We could perhaps introduce 'bind' and 'unbind' commands with similar arguments?

What kind of parameters should be used to identify the device to bind ?
I see 2 possible options:
- node paths: bind /opc/omap_dwc3@4838/usb@483d usb_ether
- device class + index: bind usb_dev 0 usb_ether.

The last one looks a lot like what I proposed, only more generic, but 
requires creating a table to match a string with a UCLASS id.

The first is more precise but IMO less user friendly.

JJ


Regards,
Simon



___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 3/3] cmd: usb gadget: Add a command to bind a USB gadget driver to a UDC port

2018-06-08 Thread Simon Glass
Hi,

On 7 June 2018 at 01:39, Lukasz Majewski  wrote:
> Hi Jean-Jacques,
>
>> Most of the time the UDC is bound to a driver when a dedicated
>> command is executed, like 'dfu'. But the ethernet gadget driver must
>> be bound by calling usb_ether_init() in the code otherwise the USB
>> ethernet adapter is not visible to the ethernet core.
>>
>> In DM context, the platform code should not be used to bind UDC to a
>> particular driver, so adding a new command to bind a USB device port
>> to a driver.
>>
>> usage example:
>> usbdev bind 0 usb_ether
>> usbdev unbind 0
>
> I would prefer a comment from Simon (so adding him to CC) - as it looks
> to me that we shall try to use DM to avoid adding separate commands for
> binding.

We could perhaps introduce 'bind' and 'unbind' commands with similar arguments?

Regards,
Simon
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 3/3] cmd: usb gadget: Add a command to bind a USB gadget driver to a UDC port

2018-06-07 Thread Lukasz Majewski
Hi Jean-Jacques,

> Most of the time the UDC is bound to a driver when a dedicated
> command is executed, like 'dfu'. But the ethernet gadget driver must
> be bound by calling usb_ether_init() in the code otherwise the USB
> ethernet adapter is not visible to the ethernet core.
> 
> In DM context, the platform code should not be used to bind UDC to a
> particular driver, so adding a new command to bind a USB device port
> to a driver.
> 
> usage example:
> usbdev bind 0 usb_ether
> usbdev unbind 0

I would prefer a comment from Simon (so adding him to CC) - as it looks
to me that we shall try to use DM to avoid adding separate commands for
binding.

> 
> Signed-off-by: Jean-Jacques Hiblot 
> 
> ---
> 
>  cmd/usb.c| 71
> +++-
> drivers/core/device-remove.c | 11 +--
> include/dm/device-internal.h | 15 ++ 3 files changed, 86
> insertions(+), 11 deletions(-)
> 
> diff --git a/cmd/usb.c b/cmd/usb.c
> index 0ccb1b5..03245cb 100644
> --- a/cmd/usb.c
> +++ b/cmd/usb.c
> @@ -14,6 +14,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -753,7 +755,6 @@ U_BOOT_CMD(
>  #endif /* CONFIG_USB_STORAGE */
>  );
>  
> -
>  #ifdef CONFIG_USB_STORAGE
>  U_BOOT_CMD(
>   usbboot,3,  1,  do_usbboot,
> @@ -761,3 +762,71 @@ U_BOOT_CMD(
>   "loadAddr dev:part"
>  );
>  #endif /* CONFIG_USB_STORAGE */
> +
> +#ifdef CONFIG_DM_USB_DEV
> +int do_usbdev(cmd_tbl_t *cmdtp, int flag, int argc, char * const
> argv[]) +{
> + struct udevice *dev;
> + struct udevice *usb_dev;
> + int port;
> + int ret;
> + bool bind;
> + static const char * const supported_drivers[] = {
> +#ifdef CONFIG_USB_ETHER
> + "usb_ether",
> +#endif
> + };
> +
> + if (argc < 2)
> + return CMD_RET_USAGE;
> +
> + if ((strncmp(argv[1], "bind", 4) == 0) && (argc == 4)) {
> + port = simple_strtoul(argv[2], NULL, 10);
> + printf("Binding USB port %d to %s\n", port, argv[3]);
> + bind = true;
> + } else if ((strncmp(argv[1], "unbind", 6) == 0) && (argc ==
> 3)) {
> + port = simple_strtoul(argv[2], NULL, 10);
> + printf("Unbinding USB port %d\n", port);
> + bind = false;
> + } else if ((strncmp(argv[1], "list", 4) == 0) && (argc ==
> 2)) {
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(supported_drivers); i++)
> + printf("%s\n", supported_drivers[i]);
> +
> + return CMD_RET_SUCCESS;
> + } else {
> + return CMD_RET_USAGE;
> + }
> +
> + ret = uclass_find_device(UCLASS_USB_DEV_GENERIC, port,
> _dev);
> + if (!usb_dev || ret) {
> + printf("Cannot find UDC %d\n", port);
> + return CMD_RET_FAILURE;
> + }
> +
> + if (bind) {
> + ret = device_bind_driver(usb_dev, argv[3], "gadget",
> );
> + if (!dev || ret) {
> + printf("Unable to bind. err:%d\n", ret);
> + return CMD_RET_FAILURE;
> + }
> + } else {
> + ret = device_chld_unbind(usb_dev);
> + if (ret) {
> + printf("Unable to bind. err:%d\n", ret);
> + return CMD_RET_FAILURE;
> + }
> + }
> +
> + return CMD_RET_SUCCESS;
> +}
> +
> +U_BOOT_CMD(
> + usbdev, 4, 0, do_usbdev,
> + "USB gadget driver",
> + "bind dev# driver- bind the USB device port to a driver\n"
> + "unbind dev# - unbind the USB device port to a driver\n"
> + "list - display the list of available gadget drivers"
> +);
> +#endif /*  CONFIG_DM_USB_DEV */
> diff --git a/drivers/core/device-remove.c
> b/drivers/core/device-remove.c index 1cf2278..b0b5ea3 100644
> --- a/drivers/core/device-remove.c
> +++ b/drivers/core/device-remove.c
> @@ -17,16 +17,7 @@
>  #include 
>  #include 
>  
> -/**
> - * device_chld_unbind() - Unbind all device's children from the
> device
> - *
> - * On error, the function continues to unbind all children, and
> reports the
> - * first error.
> - *
> - * @dev: The device that is to be stripped of its children
> - * @return 0 on success, -ve on error
> - */
> -static int device_chld_unbind(struct udevice *dev)
> +int device_chld_unbind(struct udevice *dev)
>  {
>   struct udevice *pos, *n;
>   int ret, saved_ret = 0;
> diff --git a/include/dm/device-internal.h
> b/include/dm/device-internal.h index 5a4d50c..b4f44c8 100644
> --- a/include/dm/device-internal.h
> +++ b/include/dm/device-internal.h
> @@ -120,6 +120,21 @@ int device_unbind(struct udevice *dev);
>  static inline int device_unbind(struct udevice *dev) { return 0; }
>  #endif
>  
> +/**
> + * device_chld_unbind() - Unbind all device's children from the
> device
> + *
> + * On error, the function continues to unbind all children, and
> reports the
> + * first error.
> + *
> + * @dev: The device 

[U-Boot] [PATCH v1 3/3] cmd: usb gadget: Add a command to bind a USB gadget driver to a UDC port

2018-06-04 Thread Jean-Jacques Hiblot
Most of the time the UDC is bound to a driver when a dedicated command is
executed, like 'dfu'. But the ethernet gadget driver must be bound
by calling usb_ether_init() in the code otherwise the USB ethernet adapter
is not visible to the ethernet core.

In DM context, the platform code should not be used to bind UDC to a
particular driver, so adding a new command to bind a USB device port to a
driver.

usage example:
usbdev bind 0 usb_ether
usbdev unbind 0

Signed-off-by: Jean-Jacques Hiblot 

---

 cmd/usb.c| 71 +++-
 drivers/core/device-remove.c | 11 +--
 include/dm/device-internal.h | 15 ++
 3 files changed, 86 insertions(+), 11 deletions(-)

diff --git a/cmd/usb.c b/cmd/usb.c
index 0ccb1b5..03245cb 100644
--- a/cmd/usb.c
+++ b/cmd/usb.c
@@ -14,6 +14,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -753,7 +755,6 @@ U_BOOT_CMD(
 #endif /* CONFIG_USB_STORAGE */
 );
 
-
 #ifdef CONFIG_USB_STORAGE
 U_BOOT_CMD(
usbboot,3,  1,  do_usbboot,
@@ -761,3 +762,71 @@ U_BOOT_CMD(
"loadAddr dev:part"
 );
 #endif /* CONFIG_USB_STORAGE */
+
+#ifdef CONFIG_DM_USB_DEV
+int do_usbdev(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+   struct udevice *dev;
+   struct udevice *usb_dev;
+   int port;
+   int ret;
+   bool bind;
+   static const char * const supported_drivers[] = {
+#ifdef CONFIG_USB_ETHER
+   "usb_ether",
+#endif
+   };
+
+   if (argc < 2)
+   return CMD_RET_USAGE;
+
+   if ((strncmp(argv[1], "bind", 4) == 0) && (argc == 4)) {
+   port = simple_strtoul(argv[2], NULL, 10);
+   printf("Binding USB port %d to %s\n", port, argv[3]);
+   bind = true;
+   } else if ((strncmp(argv[1], "unbind", 6) == 0) && (argc == 3)) {
+   port = simple_strtoul(argv[2], NULL, 10);
+   printf("Unbinding USB port %d\n", port);
+   bind = false;
+   } else if ((strncmp(argv[1], "list", 4) == 0) && (argc == 2)) {
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(supported_drivers); i++)
+   printf("%s\n", supported_drivers[i]);
+
+   return CMD_RET_SUCCESS;
+   } else {
+   return CMD_RET_USAGE;
+   }
+
+   ret = uclass_find_device(UCLASS_USB_DEV_GENERIC, port, _dev);
+   if (!usb_dev || ret) {
+   printf("Cannot find UDC %d\n", port);
+   return CMD_RET_FAILURE;
+   }
+
+   if (bind) {
+   ret = device_bind_driver(usb_dev, argv[3], "gadget", );
+   if (!dev || ret) {
+   printf("Unable to bind. err:%d\n", ret);
+   return CMD_RET_FAILURE;
+   }
+   } else {
+   ret = device_chld_unbind(usb_dev);
+   if (ret) {
+   printf("Unable to bind. err:%d\n", ret);
+   return CMD_RET_FAILURE;
+   }
+   }
+
+   return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+   usbdev, 4, 0, do_usbdev,
+   "USB gadget driver",
+   "bind dev# driver- bind the USB device port to a driver\n"
+   "unbind dev# - unbind the USB device port to a driver\n"
+   "list - display the list of available gadget drivers"
+);
+#endif /*  CONFIG_DM_USB_DEV */
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 1cf2278..b0b5ea3 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -17,16 +17,7 @@
 #include 
 #include 
 
-/**
- * device_chld_unbind() - Unbind all device's children from the device
- *
- * On error, the function continues to unbind all children, and reports the
- * first error.
- *
- * @dev:   The device that is to be stripped of its children
- * @return 0 on success, -ve on error
- */
-static int device_chld_unbind(struct udevice *dev)
+int device_chld_unbind(struct udevice *dev)
 {
struct udevice *pos, *n;
int ret, saved_ret = 0;
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 5a4d50c..b4f44c8 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -120,6 +120,21 @@ int device_unbind(struct udevice *dev);
 static inline int device_unbind(struct udevice *dev) { return 0; }
 #endif
 
+/**
+ * device_chld_unbind() - Unbind all device's children from the device
+ *
+ * On error, the function continues to unbind all children, and reports the
+ * first error.
+ *
+ * @dev:   The device that is to be stripped of its children
+ * @return 0 on success, -ve on error
+ */
+#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
+int device_chld_unbind(struct udevice *dev);
+#else
+static inline int device_chld_unbind(struct udevice *dev) { return 0; }
+#endif
+
 #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
 void device_free(struct udevice *dev);
 #else
-- 
2.7.4