Commit ce9bf107 authored by Efrain Calderon's avatar Efrain Calderon Committed by Carles Cufi
Browse files

devicetree: introduce DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY



Add a new macro, DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY
name, evaluates to 1 if any enabled instance of `compat` has the
property or to zero if it hasn't.

This macro can be useful in drivers for a family of devices.

Signed-off-by: default avatarEfrain Calderon <efrain.calderon.estrada@gmail.com>
parent 8b914f68
Loading
Loading
Loading
Loading
+77 −5
Original line number Diff line number Diff line
@@ -3201,7 +3201,7 @@
 */
#define DT_FOREACH_STATUS_OKAY(compat, fn)				\
	COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(compat),			\
		    (DT_CAT(DT_FOREACH_OKAY_, compat)(fn)),	\
		    (UTIL_CAT(DT_FOREACH_OKAY_, compat)(fn)),		\
		    ())

/**
@@ -3254,6 +3254,25 @@
			      compat)(fn, __VA_ARGS__)),		\
		    ())

/**
 * @brief Call @p fn on all nodes with compatible `compat`
 *        and status `okay` with multiple arguments
 *
 *
 * @param compat lowercase-and-underscores devicetree compatible
 * @param fn Macro to call for each enabled node. Must accept a
 *           devicetree compatible and instance number.
 * @param ... Additional arguments to pass to @p fn
 *
 * @see DT_INST_FOREACH_STATUS_OKAY_VARGS
 */
#define DT_COMPAT_FOREACH_STATUS_OKAY_VARGS(compat, fn, ...)		\
	COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(compat),			\
		    (UTIL_CAT(DT_FOREACH_OKAY_INST_VARGS_,		\
			      compat)(fn, compat, __VA_ARGS__)),	\
		    ())


/**
 * @brief Invokes @p fn for each node label of a given node
 *
@@ -4459,6 +4478,52 @@
#define DT_ANY_INST_HAS_PROP_STATUS_OKAY(prop) \
	COND_CODE_1(IS_EMPTY(DT_ANY_INST_HAS_PROP_STATUS_OKAY_(prop)), (0), (1))

/**
 * @brief Check if any device node with status `okay` has a given
 *        property.
 *
 * @param prop lowercase-and-underscores property name
 *
 * Example devicetree overlay:
 *
 * @code{.dts}
 *     &i2c0 {
 *         sensor0: sensor@0 {
 *             compatible = "vnd,some-sensor";
 *             status = "okay";
 *             reg = <0>;
 *             foo = <1>;
 *             bar = <2>;
 *         };
 *
 *         sensor1: sensor@1 {
 *             compatible = "vnd,some-sensor";
 *             status = "okay";
 *             reg = <1>;
 *             foo = <2>;
 *         };
 *
 *         sensor2: sensor@2 {
 *             compatible = "vnd,some-sensor";
 *             status = "disabled";
 *             reg = <2>;
 *             baz = <1>;
 *         };
 *     };
 * @endcode
 *
 * Example usage:
 *
 * @code{.c}
 *
 *     DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(vnd_some_sensor, foo) // 1
 *     DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(vnd_some_sensor, bar) // 1
 *     DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(vnd_some_sensor, baz) // 0
 * @endcode
 */
#define DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(compat, prop) \
	(DT_COMPAT_FOREACH_STATUS_OKAY_VARGS(compat, DT_COMPAT_NODE_HAS_PROP_AND_OR, prop) 0)

/**
 * @brief Call @p fn on all nodes with compatible `DT_DRV_COMPAT`
 *        and status `okay`
@@ -4536,10 +4601,11 @@
 *
 *
 * @param fn Macro to call for each enabled node. Must accept an
 *           instance number as its only parameter.
 *           instance number.
 * @param ... variable number of arguments to pass to @p fn
 *
 * @see DT_INST_FOREACH_STATUS_OKAY
 * @see DT_COMPAT_FOREACH_STATUS_OKAY_VARGS
 */
#define DT_INST_FOREACH_STATUS_OKAY_VARGS(fn, ...) \
	COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT),   \
@@ -4806,6 +4872,12 @@
#define DT_NODE_HAS_STATUS_INTERNAL(node_id, status) \
	IS_ENABLED(DT_CAT3(node_id, _STATUS_, status))

/** @brief Helper macro to OR multiple has property checks in a loop macro
 *         (for the specified device)
 */
#define DT_COMPAT_NODE_HAS_PROP_AND_OR(inst, compat, prop) \
	DT_NODE_HAS_PROP(DT_INST(inst, compat), prop) ||

/**
 * @def DT_U64_C
 * @brief Macro to add ULL postfix to the devicetree address constants
+22 −0
Original line number Diff line number Diff line
@@ -211,6 +211,16 @@ ZTEST(devicetree_api, test_any_inst_prop)
		      1, "");
}

#undef DT_DRV_COMPAT
ZTEST(devicetree_api, test_any_compat_inst_prop)
{
	zassert_equal(DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(vnd_device_with_props, foo), 1, "");
	zassert_equal(DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(vnd_device_with_props, bar), 1, "");
	zassert_equal(DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(vnd_device_with_props, baz), 0, "");
	zassert_equal(DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(vnd_device_with_props, does_not_exist),
		      0, "");
}

ZTEST(devicetree_api, test_default_prop_access)
{
	/*
@@ -1595,6 +1605,18 @@ ZTEST(devicetree_api, test_foreach_status_okay)
	val = DT_FOREACH_STATUS_OKAY_VARGS(vnd_enum_holder, MY_FN, +) 3;
	zassert_equal(val, 5, "");

#undef MY_FN
#define MY_FN(inst, compat, operator) DT_ENUM_IDX(DT_INST(inst, compat), val) operator
	/* This should expand to something like:
	 *
	 * 0 + 2 + 3
	 *
	 * and order of expansion doesn't matter, since we're adding
	 * the values all up.
	 */
	val = DT_COMPAT_FOREACH_STATUS_OKAY_VARGS(vnd_enum_holder, MY_FN, +) 3;
	zassert_equal(val, 5, "");

	/*
	 * Make sure DT_INST_FOREACH_STATUS_OKAY can be called from functions
	 * using macros with side effects in the current scope.