device.h: add DEVICE_DT_GET_ANY

Various samples are using the DT_INST macros to get devicetree node
identifiers, and going from there in the usual way to get a struct
device*.

This is undesirable for preparing a simple sample application:

1. The devicetree instance number space's rules are both complicated
   and irrelevant outside of device drivers. Using this number space
   just to get a node identifier is distracting and confusing in this
   context.

2. A basic "get the device and use the API" sample doesn't care about
   the *devicetree node identifier*; it really just wants a *device*.
   Introducing node identifiers at all is also kind of beside the
   point.

The only good reason to use DT_INST macros is that they guarantee that
instance number 0 refers to an enabled node with a given compatible,
as long as there is at least one. But the extra complexity isn't
really worth the benefit.

Add a new DEVICE_DT_GET_ANY(compat) macro that solves both of these
problems, by returning an arbitrary device structure straight from a
compatible. This uses INST numbers behind the scenes, but that's now
an implementation detail.

This avoids introducing INST numbers or node identifiers where they
are not needed, without requiring warts like sample-specific aliases
that point at the right devicetree node.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
diff --git a/include/device.h b/include/device.h
index 460ea58..2fcc4f6 100644
--- a/include/device.h
+++ b/include/device.h
@@ -257,6 +257,29 @@
 #define DEVICE_DT_INST_GET(inst) DEVICE_DT_GET(DT_DRV_INST(inst))
 
 /**
+ * @def DEVICE_DT_GET_ANY
+ *
+ * @brief Obtain a pointer to a device object by devicetree compatible
+ *
+ * If any enabled devicetree node has the given compatible and a
+ * device object was created from it, this returns that device.
+ *
+ * If there no such devices, this returns NULL.
+ *
+ * If there are multiple, this returns an arbitrary one.
+ *
+ * If this returns non-NULL, the device must be checked for readiness
+ * before use, e.g. with device_is_ready().
+ *
+ * @param compat lowercase-and-underscores devicetree compatible
+ * @return a pointer to a device, or NULL
+ */
+#define DEVICE_DT_GET_ANY(compat)			\
+	COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(compat),	\
+		    (DEVICE_DT_GET(DT_INST(0, compat))),	\
+		    (NULL))
+
+/**
  * @def DEVICE_GET
  *
  * @brief Obtain a pointer to a device object by name