dm: core: Require users of devres to include the header
[oweals/u-boot.git] / include / dm / device.h
index c825d472366a33d810b8adda8e9d7b88701839a4..2d8b716ef5e951fd1f5501170762526250e6f353 100644 (file)
@@ -1,22 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (c) 2013 Google, Inc
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
  * Marek Vasut <marex@denx.de>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #ifndef _DM_DEVICE_H
 #define _DM_DEVICE_H
 
+#include <dm/ofnode.h>
 #include <dm/uclass-id.h>
 #include <fdtdec.h>
 #include <linker_lists.h>
 #include <linux/compat.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/printk.h>
 
 struct driver_info;
 
@@ -44,8 +45,50 @@ struct driver_info;
 /* Device name is allocated and should be freed on unbind() */
 #define DM_FLAG_NAME_ALLOCED           (1 << 7)
 
+/* Device has platform data provided by of-platdata */
 #define DM_FLAG_OF_PLATDATA            (1 << 8)
 
+/*
+ * Call driver remove function to stop currently active DMA transfers or
+ * give DMA buffers back to the HW / controller. This may be needed for
+ * some drivers to do some final stage cleanup before the OS is called
+ * (U-Boot exit)
+ */
+#define DM_FLAG_ACTIVE_DMA             (1 << 9)
+
+/*
+ * Call driver remove function to do some final configuration, before
+ * U-Boot exits and the OS is started
+ */
+#define DM_FLAG_OS_PREPARE             (1 << 10)
+
+/* DM does not enable/disable the power domains corresponding to this device */
+#define DM_FLAG_DEFAULT_PD_CTRL_OFF    (1 << 11)
+
+/* Driver platdata has been read. Cleared when the device is removed */
+#define DM_FLAG_PLATDATA_VALID         (1 << 12)
+
+/*
+ * One or multiple of these flags are passed to device_remove() so that
+ * a selective device removal as specified by the remove-stage and the
+ * driver flags can be done.
+ */
+enum {
+       /* Normal remove, remove all devices */
+       DM_REMOVE_NORMAL     = 1 << 0,
+
+       /* Remove devices with active DMA */
+       DM_REMOVE_ACTIVE_DMA = DM_FLAG_ACTIVE_DMA,
+
+       /* Remove devices which need some final OS preparation steps */
+       DM_REMOVE_OS_PREPARE = DM_FLAG_OS_PREPARE,
+
+       /* Add more use cases here */
+
+       /* Remove devices with any active flag */
+       DM_REMOVE_ACTIVE_ALL = DM_REMOVE_ACTIVE_DMA | DM_REMOVE_OS_PREPARE,
+};
+
 /**
  * struct udevice - An instance of a driver
  *
@@ -68,7 +111,7 @@ struct driver_info;
  * @platdata: Configuration data for this device
  * @parent_platdata: The parent bus's configuration data for this device
  * @uclass_platdata: The uclass's configuration data for this device
- * @of_offset: Device tree node offset for this device (- for none)
+ * @node: Reference to device tree node for this device
  * @driver_data: Driver data word for the entry that matched this device with
  *             its driver
  * @parent: Parent of this device, or NULL for the top level device
@@ -94,7 +137,7 @@ struct udevice {
        void *platdata;
        void *parent_platdata;
        void *uclass_platdata;
-       int of_offset;
+       ofnode node;
        ulong driver_data;
        struct udevice *parent;
        void *priv;
@@ -121,6 +164,21 @@ struct udevice {
 /* Returns non-zero if the device is active (probed and not removed) */
 #define device_active(dev)     ((dev)->flags & DM_FLAG_ACTIVATED)
 
+static inline int dev_of_offset(const struct udevice *dev)
+{
+       return ofnode_to_offset(dev->node);
+}
+
+static inline void dev_set_of_offset(struct udevice *dev, int of_offset)
+{
+       dev->node = offset_to_ofnode(of_offset);
+}
+
+static inline bool dev_has_of_node(struct udevice *dev)
+{
+       return ofnode_valid(dev->node);
+}
+
 /**
  * struct udevice_id - Lists the compatible strings supported by a driver
  * @compatible: Compatible string
@@ -151,7 +209,7 @@ struct udevice_id {
  * it.
  *
  * @name: Device name
- * @id: Identiies the uclass we belong to
+ * @id: Identifies the uclass we belong to
  * @of_match: List of compatible strings to match, and any identifying data
  * for each.
  * @bind: Called to bind a device to its driver
@@ -207,6 +265,10 @@ struct driver {
 #define U_BOOT_DRIVER(__name)                                          \
        ll_entry_declare(struct driver, __name, driver)
 
+/* Get a pointer to a given driver */
+#define DM_GET_DRIVER(__name)                                          \
+       ll_entry_get(struct driver, __name, driver)
+
 /**
  * dev_get_platdata() - Get the platform data for a device
  *
@@ -215,7 +277,7 @@ struct driver {
  * @dev                Device to check
  * @return platform data, or NULL if none
  */
-void *dev_get_platdata(struct udevice *dev);
+void *dev_get_platdata(const struct udevice *dev);
 
 /**
  * dev_get_parent_platdata() - Get the parent platform data for a device
@@ -225,7 +287,7 @@ void *dev_get_platdata(struct udevice *dev);
  * @dev                Device to check
  * @return parent's platform data, or NULL if none
  */
-void *dev_get_parent_platdata(struct udevice *dev);
+void *dev_get_parent_platdata(const struct udevice *dev);
 
 /**
  * dev_get_uclass_platdata() - Get the uclass platform data for a device
@@ -235,7 +297,7 @@ void *dev_get_parent_platdata(struct udevice *dev);
  * @dev                Device to check
  * @return uclass's platform data, or NULL if none
  */
-void *dev_get_uclass_platdata(struct udevice *dev);
+void *dev_get_uclass_platdata(const struct udevice *dev);
 
 /**
  * dev_get_priv() - Get the private data for a device
@@ -245,7 +307,7 @@ void *dev_get_uclass_platdata(struct udevice *dev);
  * @dev                Device to check
  * @return private data, or NULL if none
  */
-void *dev_get_priv(struct udevice *dev);
+void *dev_get_priv(const struct udevice *dev);
 
 /**
  * dev_get_parent_priv() - Get the parent private data for a device
@@ -259,7 +321,7 @@ void *dev_get_priv(struct udevice *dev);
  * @dev                Device to check
  * @return parent data, or NULL if none
  */
-void *dev_get_parent_priv(struct udevice *dev);
+void *dev_get_parent_priv(const struct udevice *dev);
 
 /**
  * dev_get_uclass_priv() - Get the private uclass data for a device
@@ -269,7 +331,7 @@ void *dev_get_parent_priv(struct udevice *dev);
  * @dev                Device to check
  * @return private uclass data for this device, or NULL if none
  */
-void *dev_get_uclass_priv(struct udevice *dev);
+void *dev_get_uclass_priv(const struct udevice *dev);
 
 /**
  * struct dev_get_parent() - Get the parent of a device
@@ -277,7 +339,7 @@ void *dev_get_uclass_priv(struct udevice *dev);
  * @child:     Child to check
  * @return parent of child, or NULL if this is the root device
  */
-struct udevice *dev_get_parent(struct udevice *child);
+struct udevice *dev_get_parent(const struct udevice *child);
 
 /**
  * dev_get_driver_data() - get the driver data used to bind a device
@@ -304,7 +366,7 @@ struct udevice *dev_get_parent(struct udevice *child);
  * @dev:       Device to check
  * @return driver data (0 if none is provided)
  */
-ulong dev_get_driver_data(struct udevice *dev);
+ulong dev_get_driver_data(const struct udevice *dev);
 
 /**
  * dev_get_driver_ops() - get the device's driver's operations
@@ -315,7 +377,7 @@ ulong dev_get_driver_data(struct udevice *dev);
  * @dev:       Device to check
  * @return void pointer to driver's operations or NULL for NULL-dev or NULL-ops
  */
-const void *dev_get_driver_ops(struct udevice *dev);
+const void *dev_get_driver_ops(const struct udevice *dev);
 
 /**
  * device_get_uclass_id() - return the uclass ID of a device
@@ -323,7 +385,7 @@ const void *dev_get_driver_ops(struct udevice *dev);
  * @dev:       Device to check
  * @return uclass ID for the device
  */
-enum uclass_id device_get_uclass_id(struct udevice *dev);
+enum uclass_id device_get_uclass_id(const struct udevice *dev);
 
 /**
  * dev_get_uclass_name() - return the uclass name of a device
@@ -333,7 +395,7 @@ enum uclass_id device_get_uclass_id(struct udevice *dev);
  * @dev:       Device to check
  * @return  pointer to the uclass name for the device
  */
-const char *dev_get_uclass_name(struct udevice *dev);
+const char *dev_get_uclass_name(const struct udevice *dev);
 
 /**
  * device_get_child() - Get the child of a device by index
@@ -347,7 +409,17 @@ const char *dev_get_uclass_name(struct udevice *dev);
  * @return 0 if OK, -ENODEV if no such device, other error if the device fails
  *        to probe
  */
-int device_get_child(struct udevice *parent, int index, struct udevice **devp);
+int device_get_child(const struct udevice *parent, int index,
+                    struct udevice **devp);
+
+/**
+ * device_get_child_count() - Get the available child count of a device
+ *
+ * Returns the number of children to a device.
+ *
+ * @parent:    Parent device to check
+ */
+int device_get_child_count(const struct udevice *parent);
 
 /**
  * device_find_child_by_seq() - Find a child device based on a sequence
@@ -368,7 +440,7 @@ int device_get_child(struct udevice *parent, int index, struct udevice **devp);
  * Set to NULL if none is found
  * @return 0 if OK, -ve on error
  */
-int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
+int device_find_child_by_seq(const struct udevice *parent, int seq_or_req_seq,
                             bool find_req_seq, struct udevice **devp);
 
 /**
@@ -386,7 +458,7 @@ int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
  * Set to NULL if none is found
  * @return 0 if OK, -ve on error
  */
-int device_get_child_by_seq(struct udevice *parent, int seq,
+int device_get_child_by_seq(const struct udevice *parent, int seq,
                            struct udevice **devp);
 
 /**
@@ -399,7 +471,7 @@ int device_get_child_by_seq(struct udevice *parent, int seq,
  * @devp: Returns pointer to device if found, otherwise this is set to NULL
  * @return 0 if OK, -ve on error
  */
-int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
+int device_find_child_by_of_offset(const struct udevice *parent, int of_offset,
                                   struct udevice **devp);
 
 /**
@@ -414,22 +486,37 @@ int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
  * @devp: Returns pointer to device if found, otherwise this is set to NULL
  * @return 0 if OK, -ve on error
  */
-int device_get_child_by_of_offset(struct udevice *parent, int of_offset,
+int device_get_child_by_of_offset(const struct udevice *parent, int of_offset,
                                  struct udevice **devp);
 
 /**
- * device_get_global_by_of_offset() - Get a device based on FDT offset
+ * device_find_global_by_ofnode() - Get a device based on ofnode
+ *
+ * Locates a device by its device tree ofnode, searching globally throughout
+ * the all driver model devices.
+ *
+ * The device is NOT probed
+ *
+ * @node: Device tree ofnode to find
+ * @devp: Returns pointer to device if found, otherwise this is set to NULL
+ * @return 0 if OK, -ve on error
+ */
+
+int device_find_global_by_ofnode(ofnode node, struct udevice **devp);
+
+/**
+ * device_get_global_by_ofnode() - Get a device based on ofnode
  *
- * Locates a device by its device tree offset, searching globally throughout
+ * Locates a device by its device tree ofnode, searching globally throughout
  * the all driver model devices.
  *
  * The device is probed to activate it ready for use.
  *
- * @of_offset: Device tree offset to find
+ * @node: Device tree ofnode to find
  * @devp: Returns pointer to device if found, otherwise this is set to NULL
  * @return 0 if OK, -ve on error
  */
-int device_get_global_by_of_offset(int of_offset, struct udevice **devp);
+int device_get_global_by_ofnode(ofnode node, struct udevice **devp);
 
 /**
  * device_find_first_child() - Find the first child of a device
@@ -438,7 +525,8 @@ int device_get_global_by_of_offset(int of_offset, struct udevice **devp);
  * @devp: Returns first child device, or NULL if none
  * @return 0
  */
-int device_find_first_child(struct udevice *parent, struct udevice **devp);
+int device_find_first_child(const struct udevice *parent,
+                           struct udevice **devp);
 
 /**
  * device_find_next_child() - Find the next child of a device
@@ -450,59 +538,91 @@ int device_find_first_child(struct udevice *parent, struct udevice **devp);
 int device_find_next_child(struct udevice **devp);
 
 /**
- * dev_get_addr() - Get the reg property of a device
+ * device_find_first_inactive_child() - Find the first inactive child
+ *
+ * This is used to locate an existing child of a device which is of a given
+ * uclass.
  *
- * @dev: Pointer to a device
+ * The device is NOT probed
  *
- * @return addr
+ * @parent:    Parent device to search
+ * @uclass_id: Uclass to look for
+ * @devp:      Returns device found, if any
+ * @return 0 if found, else -ENODEV
  */
-fdt_addr_t dev_get_addr(struct udevice *dev);
+int device_find_first_inactive_child(const struct udevice *parent,
+                                    enum uclass_id uclass_id,
+                                    struct udevice **devp);
 
 /**
- * dev_get_addr_ptr() - Return pointer to the address of the reg property
- *                      of a device
+ * device_find_first_child_by_uclass() - Find the first child of a device in uc
  *
- * @dev: Pointer to a device
+ * @parent: Parent device to search
+ * @uclass_id: Uclass to look for
+ * @devp: Returns first child device in that uclass, if any
+ * @return 0 if found, else -ENODEV
+ */
+int device_find_first_child_by_uclass(const struct udevice *parent,
+                                     enum uclass_id uclass_id,
+                                     struct udevice **devp);
+
+/**
+ * device_find_child_by_name() - Find a child by device name
  *
- * @return Pointer to addr, or NULL if there is no such property
+ * @parent:    Parent device to search
+ * @name:      Name to look for
+ * @devp:      Returns device found, if any
+ * @return 0 if found, else -ENODEV
  */
-void *dev_get_addr_ptr(struct udevice *dev);
+int device_find_child_by_name(const struct udevice *parent, const char *name,
+                             struct udevice **devp);
 
 /**
- * dev_map_physmem() - Read device address from reg property of the
- *                     device node and map the address into CPU address
- *                     space.
+ * device_first_child_ofdata_err() - Find the first child and reads its platdata
  *
- * @dev: Pointer to device
- * @size: size of the memory to map
+ * The ofdata_to_platdata() method is called on the child before it is returned,
+ * but the child is not probed.
  *
- * @return  mapped address, or NULL if the device does not have reg
- *          property.
+ * @parent: Parent to check
+ * @devp: Returns child that was found, if any
+ * @return 0 on success, -ENODEV if no children, other -ve on error
  */
-void *dev_map_physmem(struct udevice *dev, unsigned long size);
+int device_first_child_ofdata_err(struct udevice *parent,
+                                 struct udevice **devp);
+
+/*
+ * device_next_child_ofdata_err() - Find the next child and read its platdata
+ *
+ * The ofdata_to_platdata() method is called on the child before it is returned,
+ * but the child is not probed.
+ *
+ * @devp: On entry, points to the previous child; on exit returns the child that
+ *     was found, if any
+ * @return 0 on success, -ENODEV if no children, other -ve on error
+ */
+int device_next_child_ofdata_err(struct udevice **devp);
 
 /**
- * dev_get_addr_index() - Get the indexed reg property of a device
+ * device_first_child_err() - Get the first child of a device
  *
- * @dev: Pointer to a device
- * @index: the 'reg' property can hold a list of <addr, size> pairs
- *        and @index is used to select which one is required
+ * The device returned is probed if necessary, and ready for use
  *
- * @return addr
+ * @parent:    Parent device to search
+ * @devp:      Returns device found, if any
+ * @return 0 if found, -ENODEV if not, -ve error if device failed to probe
  */
-fdt_addr_t dev_get_addr_index(struct udevice *dev, int index);
+int device_first_child_err(struct udevice *parent, struct udevice **devp);
 
 /**
- * dev_get_addr_name() - Get the reg property of a device, indexed by name
+ * device_next_child_err() - Get the next child of a parent device
  *
- * @dev: Pointer to a device
- * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
- *       'reg-names' property providing named-based identification. @index
- *       indicates the value to search for in 'reg-names'.
+ * The device returned is probed if necessary, and ready for use
  *
- * @return addr
+ * @devp: On entry, pointer to device to lookup. On exit, returns pointer
+ * to the next sibling if no error occurred
+ * @return 0 if found, -ENODEV if not, -ve error if device failed to probe
  */
-fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name);
+int device_next_child_err(struct udevice **devp);
 
 /**
  * device_has_children() - check if a device has any children
@@ -510,7 +630,7 @@ fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name);
  * @dev:       Device to check
  * @return true if the device has one or more children
  */
-bool device_has_children(struct udevice *dev);
+bool device_has_children(const struct udevice *dev);
 
 /**
  * device_has_active_children() - check if a device has any active children
@@ -519,7 +639,7 @@ bool device_has_children(struct udevice *dev);
  * @return true if the device has one or more children and at least one of
  * them is active (probed).
  */
-bool device_has_active_children(struct udevice *dev);
+bool device_has_active_children(const struct udevice *dev);
 
 /**
  * device_is_last_sibling() - check if a device is the last sibling
@@ -532,7 +652,7 @@ bool device_has_active_children(struct udevice *dev);
  * @return true if there are no more siblings after this one - i.e. is it
  * last in the list.
  */
-bool device_is_last_sibling(struct udevice *dev);
+bool device_is_last_sibling(const struct udevice *dev);
 
 /**
  * device_set_name() - set the name of a device
@@ -563,7 +683,7 @@ int device_set_name(struct udevice *dev, const char *name);
 void device_set_name_alloced(struct udevice *dev);
 
 /**
- * of_device_is_compatible() - check if the device is compatible with the compat
+ * device_is_compatible() - check if the device is compatible with the compat
  *
  * This allows to check whether the device is comaptible with the compat.
  *
@@ -572,7 +692,7 @@ void device_set_name_alloced(struct udevice *dev);
  *             device
  * @return true if OK, false if the compatible is not found
  */
-bool of_device_is_compatible(struct udevice *dev, const char *compat);
+bool device_is_compatible(const struct udevice *dev, const char *compat);
 
 /**
  * of_machine_is_compatible() - check if the machine is compatible with
@@ -585,13 +705,29 @@ bool of_device_is_compatible(struct udevice *dev, const char *compat);
  */
 bool of_machine_is_compatible(const char *compat);
 
+/**
+ * dev_disable_by_path() - Disable a device given its device tree path
+ *
+ * @path:      The device tree path identifying the device to be disabled
+ * @return 0 on success, -ve on error
+ */
+int dev_disable_by_path(const char *path);
+
+/**
+ * dev_enable_by_path() - Enable a device given its device tree path
+ *
+ * @path:      The device tree path identifying the device to be enabled
+ * @return 0 on success, -ve on error
+ */
+int dev_enable_by_path(const char *path);
+
 /**
  * device_is_on_pci_bus - Test if a device is on a PCI bus
  *
  * @dev:       device to test
  * @return:    true if it is on a PCI bus, false otherwise
  */
-static inline bool device_is_on_pci_bus(struct udevice *dev)
+static inline bool device_is_on_pci_bus(const struct udevice *dev)
 {
        return device_get_uclass_id(dev->parent) == UCLASS_PCI;
 }
@@ -608,280 +744,134 @@ static inline bool device_is_on_pci_bus(struct udevice *dev)
 #define device_foreach_child_safe(pos, next, parent)   \
        list_for_each_entry_safe(pos, next, &parent->child_head, sibling_node)
 
-/* device resource management */
-typedef void (*dr_release_t)(struct udevice *dev, void *res);
-typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
-
-#ifdef CONFIG_DEVRES
-
-#ifdef CONFIG_DEBUG_DEVRES
-void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
-                    const char *name);
-#define _devres_alloc(release, size, gfp) \
-       __devres_alloc(release, size, gfp, #release)
-#else
-void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp);
-#endif
-
-/**
- * devres_alloc() - Allocate device resource data
- * @release: Release function devres will be associated with
- * @size: Allocation size
- * @gfp: Allocation flags
- *
- * Allocate devres of @size bytes.  The allocated area is associated
- * with @release.  The returned pointer can be passed to
- * other devres_*() functions.
- *
- * RETURNS:
- * Pointer to allocated devres on success, NULL on failure.
- */
-#define devres_alloc(release, size, gfp) \
-       _devres_alloc(release, size, gfp | __GFP_ZERO)
-
-/**
- * devres_free() - Free device resource data
- * @res: Pointer to devres data to free
- *
- * Free devres created with devres_alloc().
- */
-void devres_free(void *res);
-
 /**
- * devres_add() - Register device resource
- * @dev: Device to add resource to
- * @res: Resource to register
- *
- * Register devres @res to @dev.  @res should have been allocated
- * using devres_alloc().  On driver detach, the associated release
- * function will be invoked and devres will be freed automatically.
- */
-void devres_add(struct udevice *dev, void *res);
-
-/**
- * devres_find() - Find device resource
- * @dev: Device to lookup resource from
- * @release: Look for resources associated with this release function
- * @match: Match function (optional)
- * @match_data: Data for the match function
- *
- * Find the latest devres of @dev which is associated with @release
- * and for which @match returns 1.  If @match is NULL, it's considered
- * to match all.
+ * device_foreach_child() - iterate through child devices
  *
- * @return pointer to found devres, NULL if not found.
+ * @pos: struct udevice * for the current device
+ * @parent: parent device to scan
  */
-void *devres_find(struct udevice *dev, dr_release_t release,
-                 dr_match_t match, void *match_data);
+#define device_foreach_child(pos, parent)      \
+       list_for_each_entry(pos, &parent->child_head, sibling_node)
 
 /**
- * devres_get() - Find devres, if non-existent, add one atomically
- * @dev: Device to lookup or add devres for
- * @new_res: Pointer to new initialized devres to add if not found
- * @match: Match function (optional)
- * @match_data: Data for the match function
- *
- * Find the latest devres of @dev which has the same release function
- * as @new_res and for which @match return 1.  If found, @new_res is
- * freed; otherwise, @new_res is added atomically.
+ * device_foreach_child_ofdata_to_platdata() - iterate through children
  *
- * @return ointer to found or added devres.
- */
-void *devres_get(struct udevice *dev, void *new_res,
-                dr_match_t match, void *match_data);
+ * This stops when it gets an error, with @pos set to the device that failed to
+ * read ofdata.
 
-/**
- * devres_remove() - Find a device resource and remove it
- * @dev: Device to find resource from
- * @release: Look for resources associated with this release function
- * @match: Match function (optional)
- * @match_data: Data for the match function
- *
- * Find the latest devres of @dev associated with @release and for
- * which @match returns 1.  If @match is NULL, it's considered to
- * match all.  If found, the resource is removed atomically and
- * returned.
+ * This creates a for() loop which works through the available children of
+ * a device in order from start to end. Device ofdata is read by calling
+ * device_ofdata_to_platdata() on each one. The devices are not probed.
  *
- * @return ointer to removed devres on success, NULL if not found.
+ * @pos: struct udevice * for the current device
+ * @parent: parent device to scan
  */
-void *devres_remove(struct udevice *dev, dr_release_t release,
-                   dr_match_t match, void *match_data);
+#define device_foreach_child_ofdata_to_platdata(pos, parent)   \
+       for (int _ret = device_first_child_ofdata_err(parent, &dev); !_ret; \
+            _ret = device_next_child_ofdata_err(&dev))
 
 /**
- * devres_destroy() - Find a device resource and destroy it
- * @dev: Device to find resource from
- * @release: Look for resources associated with this release function
- * @match: Match function (optional)
- * @match_data: Data for the match function
+ * device_foreach_child_probe() - iterate through children, probing them
  *
- * Find the latest devres of @dev associated with @release and for
- * which @match returns 1.  If @match is NULL, it's considered to
- * match all.  If found, the resource is removed atomically and freed.
+ * This creates a for() loop which works through the available children of
+ * a device in order from start to end. Devices are probed if necessary,
+ * and ready for use.
  *
- * Note that the release function for the resource will not be called,
- * only the devres-allocated data will be freed.  The caller becomes
- * responsible for freeing any other data.
+ * This stops when it gets an error, with @pos set to the device that failed to
+ * probe
  *
- * @return 0 if devres is found and freed, -ENOENT if not found.
+ * @pos: struct udevice * for the current device
+ * @parent: parent device to scan
  */
-int devres_destroy(struct udevice *dev, dr_release_t release,
-                  dr_match_t match, void *match_data);
+#define device_foreach_child_probe(pos, parent)        \
+       for (int _ret = device_first_child_err(parent, &dev); !_ret; \
+            _ret = device_next_child_err(&dev))
 
 /**
- * devres_release() - Find a device resource and destroy it, calling release
- * @dev: Device to find resource from
- * @release: Look for resources associated with this release function
- * @match: Match function (optional)
- * @match_data: Data for the match function
+ * dm_scan_fdt_dev() - Bind child device in a the device tree
  *
- * Find the latest devres of @dev associated with @release and for
- * which @match returns 1.  If @match is NULL, it's considered to
- * match all.  If found, the resource is removed atomically, the
- * release function called and the resource freed.
+ * This handles device which have sub-nodes in the device tree. It scans all
+ * sub-nodes and binds drivers for each node where a driver can be found.
  *
- * @return 0 if devres is found and freed, -ENOENT if not found.
- */
-int devres_release(struct udevice *dev, dr_release_t release,
-                  dr_match_t match, void *match_data);
-
-/* managed devm_k.alloc/kfree for device drivers */
-/**
- * devm_kmalloc() - Resource-managed kmalloc
- * @dev: Device to allocate memory for
- * @size: Allocation size
- * @gfp: Allocation gfp flags
- *
- * Managed kmalloc.  Memory allocated with this function is
- * automatically freed on driver detach.  Like all other devres
- * resources, guaranteed alignment is unsigned long long.
+ * If this is called prior to relocation, only pre-relocation devices will be
+ * bound (those marked with u-boot,dm-pre-reloc in the device tree, or where
+ * the driver has the DM_FLAG_PRE_RELOC flag set). Otherwise, all devices will
+ * be bound.
  *
- * @return pointer to allocated memory on success, NULL on failure.
+ * @dev:       Device to scan
+ * @return 0 if OK, -ve on error
  */
-void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp);
-static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
-{
-       return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
-}
-static inline void *devm_kmalloc_array(struct udevice *dev,
-                                      size_t n, size_t size, gfp_t flags)
-{
-       if (size != 0 && n > SIZE_MAX / size)
-               return NULL;
-       return devm_kmalloc(dev, n * size, flags);
-}
-static inline void *devm_kcalloc(struct udevice *dev,
-                                size_t n, size_t size, gfp_t flags)
-{
-       return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
-}
+int dm_scan_fdt_dev(struct udevice *dev);
 
-/**
- * devm_kfree() - Resource-managed kfree
- * @dev: Device this memory belongs to
- * @ptr: Memory to free
- *
- * Free memory allocated with devm_kmalloc().
+/*
+ * REVISIT:
+ * remove the following after resolving conflicts with <linux/compat.h>
  */
-void devm_kfree(struct udevice *dev, void *ptr);
-
-#else /* ! CONFIG_DEVRES */
-
-static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
-{
-       return kzalloc(size, gfp);
-}
-
-static inline void devres_free(void *res)
-{
-       kfree(res);
-}
-
-static inline void devres_add(struct udevice *dev, void *res)
-{
-}
-
-static inline void *devres_find(struct udevice *dev, dr_release_t release,
-                               dr_match_t match, void *match_data)
-{
-       return NULL;
-}
-
-static inline void *devres_get(struct udevice *dev, void *new_res,
-                              dr_match_t match, void *match_data)
-{
-       return NULL;
-}
-
-static inline void *devres_remove(struct udevice *dev, dr_release_t release,
-                                 dr_match_t match, void *match_data)
-{
-       return NULL;
-}
-
-static inline int devres_destroy(struct udevice *dev, dr_release_t release,
-                                dr_match_t match, void *match_data)
-{
-       return 0;
-}
-
-static inline int devres_release(struct udevice *dev, dr_release_t release,
-                                dr_match_t match, void *match_data)
-{
-       return 0;
-}
-
-static inline void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp)
-{
-       return kmalloc(size, gfp);
-}
-
-static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
-{
-       return kzalloc(size, gfp);
-}
-
-static inline void *devm_kmaloc_array(struct udevice *dev,
-                                     size_t n, size_t size, gfp_t flags)
-{
-       /* TODO: add kmalloc_array() to linux/compat.h */
-       if (size != 0 && n > SIZE_MAX / size)
-               return NULL;
-       return kmalloc(n * size, flags);
-}
-
-static inline void *devm_kcalloc(struct udevice *dev,
-                                size_t n, size_t size, gfp_t flags)
-{
-       /* TODO: add kcalloc() to linux/compat.h */
-       return kmalloc(n * size, flags | __GFP_ZERO);
-}
-
-static inline void devm_kfree(struct udevice *dev, void *ptr)
-{
-       kfree(ptr);
-}
-
-#endif /* ! CONFIG_DEVRES */
+#ifdef dev_dbg
+#undef dev_dbg
+#endif
+#ifdef dev_vdbg
+#undef dev_vdbg
+#endif
+#ifdef dev_info
+#undef dev_info
+#endif
+#ifdef dev_err
+#undef dev_err
+#endif
+#ifdef dev_warn
+#undef dev_warn
+#endif
 
-/**
- * dm_set_translation_offset() - Set translation offset
- * @offs: Translation offset
- *
- * Some platforms need a special address translation. Those
- * platforms (e.g. mvebu in SPL) can configure a translation
- * offset in the DM by calling this function. It will be
- * added to all addresses returned in dev_get_addr().
- */
-void dm_set_translation_offset(fdt_addr_t offs);
+/*
+ * REVISIT:
+ * print device name like Linux
+ */
+#define dev_printk(dev, fmt, ...)                              \
+({                                                             \
+       printk(fmt, ##__VA_ARGS__);                             \
+})
+
+#define __dev_printk(level, dev, fmt, ...)                     \
+({                                                             \
+       if (level < CONFIG_VAL(LOGLEVEL))                       \
+               dev_printk(dev, fmt, ##__VA_ARGS__);            \
+})
+
+#define dev_emerg(dev, fmt, ...) \
+       __dev_printk(0, dev, fmt, ##__VA_ARGS__)
+#define dev_alert(dev, fmt, ...) \
+       __dev_printk(1, dev, fmt, ##__VA_ARGS__)
+#define dev_crit(dev, fmt, ...) \
+       __dev_printk(2, dev, fmt, ##__VA_ARGS__)
+#define dev_err(dev, fmt, ...) \
+       __dev_printk(3, dev, fmt, ##__VA_ARGS__)
+#define dev_warn(dev, fmt, ...) \
+       __dev_printk(4, dev, fmt, ##__VA_ARGS__)
+#define dev_notice(dev, fmt, ...) \
+       __dev_printk(5, dev, fmt, ##__VA_ARGS__)
+#define dev_info(dev, fmt, ...) \
+       __dev_printk(6, dev, fmt, ##__VA_ARGS__)
+
+#ifdef DEBUG
+#define dev_dbg(dev, fmt, ...) \
+       __dev_printk(7, dev, fmt, ##__VA_ARGS__)
+#else
+#define dev_dbg(dev, fmt, ...)                                 \
+({                                                             \
+       if (0)                                                  \
+               __dev_printk(7, dev, fmt, ##__VA_ARGS__);       \
+})
+#endif
 
-/**
- * dm_get_translation_offset() - Get translation offset
- *
- * This function returns the translation offset that can
- * be configured by calling dm_set_translation_offset().
- *
- * @return translation offset for the device address (0 as default).
- */
-fdt_addr_t dm_get_translation_offset(void);
+#ifdef VERBOSE_DEBUG
+#define dev_vdbg       dev_dbg
+#else
+#define dev_vdbg(dev, fmt, ...)                                        \
+({                                                             \
+       if (0)                                                  \
+               __dev_printk(7, dev, fmt, ##__VA_ARGS__);       \
+})
+#endif
 
 #endif