dm: Introduce device sequence numbering

In U-Boot it is pretty common to number devices from 0 and access them
on the command line using this numbering. While it may come to pass that
we will move away from this numbering, the possibility seems remote at
present.

Given that devices within a uclass will have an implied numbering, it
makes sense to build this into driver model as a core feature. The cost
is fairly small in terms of code and data space.

With each uclass having numbered devices we can ask for SPI port 0 or
serial port 1 and receive a single device.

Devices typically request a sequence number using aliases in the device
tree. These are resolved when the device is probed, to deal with conflicts.
Sequence numbers need not be sequential and holes are permitted.

At present there is no support for sequence numbers using static platform
data. It could easily be added to 'struct driver_info' if needed, but it
seems better to add features as we find a use for them, and the use of -1
to mean 'no sequence' makes the default value somewhat painful.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/include/dm/device.h b/include/dm/device.h
index 4679979..6005e7e 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -55,6 +55,8 @@
  * @child_head: List of children of this device
  * @sibling_node: Next device in list of all devices
  * @flags: Flags for this device DM_FLAG_...
+ * @req_seq: Requested sequence number for this device (-1 = any)
+ * @seq: Allocated sequence number for this device (-1 = none)
  */
 struct udevice {
 	struct driver *driver;
@@ -69,8 +71,13 @@
 	struct list_head child_head;
 	struct list_head sibling_node;
 	uint32_t flags;
+	int req_seq;
+	int seq;
 };
 
+/* Maximum sequence number supported */
+#define DM_MAX_SEQ	999
+
 /* Returns the operations for a device */
 #define device_get_ops(dev)	(dev->driver->ops)
 
@@ -161,4 +168,26 @@
  */
 void *dev_get_priv(struct udevice *dev);
 
+/**
+ * device_find_child_by_seq() - Find a child device based on a sequence
+ *
+ * This searches for a device with the given seq or req_seq.
+ *
+ * For seq, if an active device has this sequence it will be returned.
+ * If there is no such device then this will return -ENODEV.
+ *
+ * For req_seq, if a device (whether activated or not) has this req_seq
+ * value, that device will be returned. This is a strong indication that
+ * the device will receive that sequence when activated.
+ *
+ * @parent: Parent device
+ * @seq_or_req_seq: Sequence number to find (0=first)
+ * @find_req_seq: true to find req_seq, false to find seq
+ * @devp: Returns pointer to device (there is only one per for each seq).
+ * 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,
+			     bool find_req_seq, struct udevice **devp);
+
 #endif