zephyr/include/devicetree.h
Martí Bolívar 8165008f44 dts: remove legacy macro support
The legacy macros were first deprecated in Zephyr v2.3. Now that
Zephyr v2.4 has been released, that makes two releases where these
macros have been deprecated, so it's OK to remove them.

This leaves support for legacy binding syntax in place. Removing that
is left to future work.

We need to update various pieces of documentation related to flash
partitions that never got updated when the new API was introduced.
Consolidate this information in the flash_map.h API reference page,
since that's really where users will run into it. This also gives us
the opportunity to improve this documentation.

Adjust a couple of kconfigfunctions.py and sanitycheck bits to use
non-legacy edtlib APIs.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2020-10-09 08:45:38 -05:00

1939 lines
62 KiB
C

/*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) 2020 Nordic Semiconductor
* Copyright (c) 2020, Linaro Ltd.
*
* Not a generated file. Feel free to modify.
*/
/**
* @file
* @brief Devicetree main header
*
* API for accessing the current application's devicetree macros.
*/
#ifndef DEVICETREE_H
#define DEVICETREE_H
#include <devicetree_unfixed.h>
#include <devicetree_fixups.h>
#include <sys/util.h>
/**
* @brief devicetree.h API
* @defgroup devicetree Devicetree
* @{
* @}
*/
/*
* Property suffixes
* -----------------
*
* These are the optional parts that come after the _P_<property>
* part in DT_N_<path-id>_P_<property-id> macros, or the "prop-suf"
* nonterminal in the DT guide's macros.bnf file.
*
* Before adding new ones, check this list to avoid conflicts. If any
* are missing from this list, please add them. It should be complete.
*
* _ENUM_IDX: property's value as an index into bindings enum
* _EXISTS: property is defined
* _IDX_<i>: logical index into property
* _IDX_<i>_PH: phandle array's phandle by index (or phandle, phandles)
* _IDX_<i>_VAL_<val>: phandle array's specifier value by index
* _IDX_<i>_VAL_<val>_EXISTS: cell value exists, by index
* _LEN: property logical length
* _NAME_<name>_PH: phandle array's phandle by name
* _NAME_<name>_VAL_<val>: phandle array's property specifier by name
* _NAME_<name>_VAL_<val>_EXISTS: cell value exists, by name
*/
/**
* @defgroup devicetree-generic-id Node identifiers
* @ingroup devicetree
* @{
*/
/**
* @brief Node identifier for the root node in the devicetree
*/
#define DT_ROOT DT_N
/**
* @brief Get a node identifier for a devicetree path
*
* The arguments to this macro are the names of non-root nodes in the
* tree required to reach the desired node, starting from the root.
* Non-alphanumeric characters in each name must be converted to
* underscores to form valid C tokens, and letters must be lowercased.
*
* Example devicetree fragment:
*
* / {
* soc {
* serial1: serial@40001000 {
* status = "okay";
* current-speed = <115200>;
* ...
* };
* };
* };
*
* You can use DT_PATH(soc, serial_40001000) to get a node identifier
* for the serial@40001000 node. Node labels like "serial1" cannot be
* used as DT_PATH() arguments; use DT_NODELABEL() for those instead.
*
* Example usage with DT_PROP() to get the current-speed property:
*
* DT_PROP(DT_PATH(soc, serial_40001000), current_speed) // 115200
*
* (The current-speed property is also in "lowercase-and-underscores"
* form when used with this API.)
*
* When determining arguments to DT_PATH():
*
* - the first argument corresponds to a child node of the root ("soc" above)
* - a second argument corresponds to a child of the first argument
* ("serial_40001000" above, from the node name "serial@40001000"
* after lowercasing and changing "@" to "_")
* - and so on for deeper nodes in the desired node's path
*
* @param ... lowercase-and-underscores node names along the node's path,
* with each name given as a separate argument
* @return node identifier for the node with that path
*/
#define DT_PATH(...) DT_PATH_INTERNAL(__VA_ARGS__)
/**
* @brief Get a node identifier for a node label
*
* Convert non-alphanumeric characters in the node label to
* underscores to form valid C tokens, and lowercase all letters. Note
* that node labels are not the same thing as label properties.
*
* Example devicetree fragment:
*
* serial1: serial@40001000 {
* label = "UART_0";
* status = "okay";
* current-speed = <115200>;
* ...
* };
*
* The only node label in this example is "serial1".
*
* The string "UART_0" is *not* a node label; it's the value of a
* property named label.
*
* You can use DT_NODELABEL(serial1) to get a node identifier for the
* serial@40001000 node. Example usage with DT_PROP() to get the
* current-speed property:
*
* DT_PROP(DT_NODELABEL(serial1), current_speed) // 115200
*
* Another example devicetree fragment:
*
* cpu@0 {
* L2_0: l2-cache {
* cache-level = <2>;
* ...
* };
* };
*
* Example usage to get the cache-level property:
*
* DT_PROP(DT_NODELABEL(l2_0), cache_level) // 2
*
* Notice how "L2_0" in the devicetree is lowercased to "l2_0" in the
* DT_NODELABEL() argument.
*
* @param label lowercase-and-underscores node label name
* @return node identifier for the node with that label
*/
#define DT_NODELABEL(label) DT_CAT(DT_N_NODELABEL_, label)
/**
* @brief Get a node identifier from /aliases
*
* This macro's argument is a property of the /aliases node. It
* returns a node identifier for the node which is aliased. Convert
* non-alphanumeric characters in the alias property to underscores to
* form valid C tokens, and lowercase all letters.
*
* Example devicetree fragment:
*
* / {
* aliases {
* my-serial = &serial1;
* };
*
* soc {
* serial1: serial@40001000 {
* status = "okay";
* current-speed = <115200>;
* ...
* };
* };
* };
*
* You can use DT_ALIAS(my_serial) to get a node identifier for the
* serial@40001000 node. Notice how my-serial in the devicetree
* becomes my_serial in the DT_ALIAS() argument. Example usage with
* DT_PROP() to get the current-speed property:
*
* DT_PROP(DT_ALIAS(my_serial), current_speed) // 115200
*
* @param alias lowercase-and-underscores alias name.
* @return node identifier for the node with that alias
*/
#define DT_ALIAS(alias) DT_CAT(DT_N_ALIAS_, alias)
/**
* @brief Get a node identifier for an instance of a compatible
*
* All nodes with a particular compatible property value are assigned
* instance numbers, which are zero-based indexes specific to that
* compatible. You can get a node identifier for these nodes by
* passing DT_INST() an instance number, "inst", along with the
* lowercase-and-underscores version of the compatible, "compat".
*
* Instance numbers have the following properties:
*
* - for each compatible, instance numbers start at 0 and are contiguous
* - exactly one instance number is assigned for each node with a compatible,
* **including disabled nodes**
* - enabled nodes (status property is "okay" or missing) are assigned the
* instance numbers starting from 0, and disabled nodes have instance
* numbers which are greater than those of any enabled node
*
* No other guarantees are made. In particular:
*
* - instance numbers **in no way reflect** any numbering scheme that
* might exist in SoC documentation, node labels or unit addresses,
* or properties of the /aliases node (use DT_NODELABEL() or DT_ALIAS()
* for those)
* - there **is no general guarantee** that the same node will have
* the same instance number between builds, even if you are building
* the same application again in the same build directory
*
* Example devicetree fragment:
*
* serial1: serial@40001000 {
* compatible = "vnd,soc-serial";
* status = "disabled";
* current-speed = <9600>;
* ...
* };
*
* serial2: serial@40002000 {
* compatible = "vnd,soc-serial";
* status = "okay";
* current-speed = <57600>;
* ...
* };
*
* serial3: serial@40003000 {
* compatible = "vnd,soc-serial";
* current-speed = <115200>;
* ...
* };
*
* Assuming no other nodes in the devicetree have compatible
* "vnd,soc-serial", that compatible has nodes with instance numbers
* 0, 1, and 2.
*
* The nodes serial@40002000 and serial@40003000 are both enabled, so
* their instance numbers are 0 and 1, but no guarantees are made
* regarding which node has which instance number.
*
* Since serial@40001000 is the only disabled node, it has instance
* number 2, since disabled nodes are assigned the largest instance
* numbers. Therefore:
*
* // Could be 57600 or 115200. There is no way to be sure:
* // either serial@40002000 or serial@40003000 could
* // have instance number 0, so this could be the current-speed
* // property of either of those nodes.
* DT_PROP(DT_INST(0, vnd_soc_serial), current_speed)
*
* // Could be 57600 or 115200, for the same reason.
* // If the above expression expands to 57600, then
* // this expands to 115200, and vice-versa.
* DT_PROP(DT_INST(1, vnd_soc_serial), current_speed)
*
* // 9600, because there is only one disabled node, and
* // disabled nodes are "at the the end" of the instance
* // number "list".
* DT_PROP(DT_INST(2, vnd_soc_serial), current_speed)
*
* Notice how "vnd,soc-serial" in the devicetree becomes vnd_soc_serial
* (without quotes) in the DT_INST() arguments. (As usual, current-speed
* in the devicetree becomes current_speed as well.)
*
* Nodes whose "compatible" property has multiple values are assigned
* independent instance numbers for each compatible.
*
* @param inst instance number for compatible "compat"
* @param compat lowercase-and-underscores compatible, without quotes
* @return node identifier for the node with that instance number and
* compatible
*/
#define DT_INST(inst, compat) UTIL_CAT(DT_N_INST, DT_DASH(inst, compat))
/**
* @brief Get a node identifier for a parent node
*
* Example devicetree fragment:
*
* parent: parent-node {
* child: child-node {
* ...
* };
* };
*
* The following are equivalent ways to get the same node identifier:
*
* DT_NODELABEL(parent)
* DT_PARENT(DT_NODELABEL(child))
*
* @param node_id node identifier
* @return a node identifier for the node's parent
*/
#define DT_PARENT(node_id) UTIL_CAT(node_id, _PARENT)
/**
* @brief Get a node identifier for a child node
*
* Example devicetree fragment:
*
* / {
* soc-label: soc {
* serial1: serial@40001000 {
* status = "okay";
* current-speed = <115200>;
* ...
* };
* };
* };
*
* Example usage with @ref DT_PROP() to get the status of the
* serial@40001000 node:
*
* #define SOC_NODE DT_NODELABEL(soc_label)
* DT_PROP(DT_CHILD(SOC_NODE, serial_40001000), status) // "okay"
*
* Node labels like "serial1" cannot be used as the "child" argument
* to this macro. Use DT_NODELABEL() for that instead.
*
* You can also use DT_FOREACH_CHILD() to iterate over node
* identifiers for all of a node's children.
*
* @param node_id node identifier
* @param child lowercase-and-underscores child node name
* @return node identifier for the node with the name referred to by 'child'
*/
#define DT_CHILD(node_id, child) UTIL_CAT(node_id, DT_S_PREFIX(child))
/**
* @}
*/
/**
* @defgroup devicetree-generic-prop Property accessors
* @ingroup devicetree
* @{
*/
/**
* @brief Get a devicetree property value
*
* For properties whose bindings have the following types, this macro
* expands to:
*
* - string: a string literal
* - boolean: 0 if the property is false, or 1 if it is true
* - int: the property's value as an integer literal
* - array, uint8-array, string-array: an initializer expression in braces,
* whose elements are integer or string literals (like {0, 1, 2},
* {"hello", "world"}, etc.)
* - phandle: a node identifier for the node with that phandle
*
* A property's type is usually defined by its binding. In some
* special cases, it has an assumed type defined by the devicetree
* specification even when no binding is available: "compatible" has
* type string-array, "status" and "label" have type string, and
* "interrupt-controller" has type boolean.
*
* For other properties or properties with unknown type due to a
* missing binding, behavior is undefined.
*
* For usage examples, see @ref DT_PATH(), @ref DT_ALIAS(), @ref
* DT_NODELABEL(), and @ref DT_INST() above.
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property name
* @return a representation of the property's value
*/
#define DT_PROP(node_id, prop) DT_CAT(node_id, _P_##prop)
/**
* @brief Get a property's logical length
*
* Here, "length" is a number of elements, which may differ from the
* property's size in bytes.
*
* The return value depends on the property's type:
*
* - for types array, string-array, and uint8-array, this expands
* to the number of elements in the array
* - for type phandles, this expands to the number of phandles
* - for type phandle-array, this expands to the number of
* phandle and specifier blocks in the property
*
* These properties are handled as special cases:
*
* - reg property: use DT_NUM_REGS(node_id) instead
* - interrupts property: use DT_NUM_IRQS(node_id) instead
*
* It is an error to use this macro with the reg or interrupts properties.
*
* For other properties, behavior is undefined.
*
* @param node_id node identifier
* @param prop a lowercase-and-underscores property with a logical length
* @return the property's length
*/
#define DT_PROP_LEN(node_id, prop) DT_PROP(node_id, prop##_LEN)
/**
* @brief Is index "idx" valid for an array type property?
*
* If this returns 1, then DT_PROP_BY_IDX(node_id, prop, idx) or
* DT_PHA_BY_IDX(node_id, prop, idx, ...) are valid at index "idx".
* If it returns 0, it is an error to use those macros with that index.
*
* These properties are handled as special cases:
*
* - reg property: use DT_REG_HAS_IDX(node_id, idx) instead
* - interrupts property: use DT_IRQ_HAS_IDX(node_id, idx) instead
*
* It is an error to use this macro with the reg or interrupts properties.
*
* @param node_id node identifier
* @param prop a lowercase-and-underscores property with a logical length
* @param idx index to check
* @return An expression which evaluates to 1 if "idx" is a valid index
* into the given property, and 0 otherwise.
*/
#define DT_PROP_HAS_IDX(node_id, prop, idx) \
((idx) < DT_PROP_LEN(node_id, prop))
/**
* @brief Get the value at index "idx" in an array type property
*
* It might help to read the argument order as being similar to
* "node->property[index]".
*
* When the property's binding has type array, string-array,
* uint8-array, or phandles, this expands to the idx-th array element
* as an integer, string literal, or node identifier respectively.
*
* These properties are handled as special cases:
*
* - reg property: use DT_REG_ADDR_BY_IDX() or DT_REG_SIZE_BY_IDX() instead
* - interrupts property: use DT_IRQ_BY_IDX() instead
*
* For non-array properties, behavior is undefined.
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property name
* @param idx the index to get
* @return a representation of the idx-th element of the property
*/
#define DT_PROP_BY_IDX(node_id, prop, idx) DT_PROP(node_id, prop##_IDX_##idx)
/**
* @brief Like DT_PROP(), but with a fallback to default_value
*
* If the value exists, this expands to DT_PROP(node_id, prop).
* The default_value parameter is not expanded in this case.
*
* Otherwise, this expands to default_value.
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property name
* @param default_value a fallback value to expand to
* @return the property's value or default_value
*/
#define DT_PROP_OR(node_id, prop, default_value) \
COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop), \
(DT_PROP(node_id, prop)), (default_value))
/**
* @brief Equivalent to DT_PROP(node_id, label)
*
* This is a convenience for the Zephyr device API, which uses label
* properties as device_get_binding() arguments.
* @param node_id node identifier
* @return node's label property value
*/
#define DT_LABEL(node_id) DT_PROP(node_id, label)
/**
* @brief Get a property value's index into its enumeration values
*
* The return values start at zero.
*
* Example devicetree fragment:
*
* usb1: usb@12340000 {
* maximum-speed = "full-speed";
* };
* usb2: usb@12341000 {
* maximum-speed = "super-speed";
* };
*
* Example bindings fragment:
*
* properties:
* maximum-speed:
* type: string
* enum:
* - "low-speed"
* - "full-speed"
* - "high-speed"
* - "super-speed"
*
* Example usage:
*
* DT_ENUM_IDX(DT_NODELABEL(usb1), maximum_speed) // 1
* DT_ENUM_IDX(DT_NODELABEL(usb2), maximum_speed) // 3
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property name
* @return zero-based index of the property's value in its enum: list
*/
#define DT_ENUM_IDX(node_id, prop) DT_PROP(node_id, prop##_ENUM_IDX)
/**
* @brief Like DT_ENUM_IDX(), but with a fallback to a default enum index
*
* If the value exists, this expands to its zero based index value thanks to
* DT_ENUM_IDX(node_id, prop).
*
* Otherwise, this expands to provided default index enum value.
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property name
* @param default_idx_value a fallback index value to expand to
* @return zero-based index of the property's value in its enum if present,
* default_idx_value ohterwise
*/
#define DT_ENUM_IDX_OR(node_id, prop, default_idx_value) \
COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop), \
(DT_ENUM_IDX(node_id, prop)), (default_idx_value))
/*
* phandle properties
*
* These are special-cased to manage the impedance mismatch between
* phandles, which are just uint32_t node properties that only make sense
* within the tree itself, and C values.
*/
/**
* @brief Get a property value from a phandle in a property.
*
* This is a shorthand for:
*
* DT_PROP(DT_PHANDLE_BY_IDX(node_id, phs, idx), prop)
*
* That is, "prop" is a property of the phandle's node, not a
* property of "node_id".
*
* Example devicetree fragment:
*
* n1: node-1 {
* foo = <&n2 &n3>;
* };
*
* n2: node-2 {
* bar = <42>;
* };
*
* n3: node-3 {
* baz = <43>;
* };
*
* Example usage:
*
* #define N1 DT_NODELABEL(n1)
*
* DT_PROP_BY_PHANDLE_IDX(N1, foo, 0, bar) // 42
* DT_PROP_BY_PHANDLE_IDX(N1, foo, 1, baz) // 43
*
* @param node_id node identifier
* @param phs lowercase-and-underscores property with type "phandle",
* "phandles", or "phandle-array"
* @param idx logical index into "phs", which must be zero if "phs"
* has type "phandle"
* @param prop lowercase-and-underscores property of the phandle's node
* @return the property's value
*/
#define DT_PROP_BY_PHANDLE_IDX(node_id, phs, idx, prop) \
DT_PROP(DT_PHANDLE_BY_IDX(node_id, phs, idx), prop)
/**
* @brief Get a property value from a phandle's node
*
* This is equivalent to DT_PROP_BY_PHANDLE_IDX(node_id, ph, 0, prop).
*
* @param node_id node identifier
* @param ph lowercase-and-underscores property of "node_id"
* with type "phandle"
* @param prop lowercase-and-underscores property of the phandle's node
* @return the property's value
*/
#define DT_PROP_BY_PHANDLE(node_id, ph, prop) \
DT_PROP_BY_PHANDLE_IDX(node_id, ph, 0, prop)
/**
* @brief Get a phandle-array specifier cell value at an index
*
* It might help to read the argument order as being similar to
* "node->phandle_array[index].cell". That is, the cell value is in
* the "pha" property of "node_id", inside the specifier at index
* "idx".
*
* Example devicetree fragment:
*
* gpio0: gpio@... {
* #gpio-cells = <2>;
* };
*
* gpio1: gpio@... {
* #gpio-cells = <2>;
* };
*
* led: led_0 {
* gpios = <&gpio0 17 0x1>, <&gpio1 5 0x3>;
* };
*
* Bindings fragment for the gpio0 and gpio1 nodes:
*
* gpio-cells:
* - pin
* - flags
*
* Above, "gpios" has two elements:
*
* - index 0 has specifier <17 0x1>, so its "pin" cell is 17, and its
* "flags" cell is 0x1
* - index 1 has specifier <5 0x3>, so "pin" is 5 and "flags" is 0x3
*
* Example usage:
*
* #define LED DT_NODELABEL(led)
*
* DT_PHA_BY_IDX(LED, gpios, 0, pin) // 17
* DT_PHA_BY_IDX(LED, gpios, 1, flags) // 0x3
*
* @param node_id node identifier
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param idx logical index into "pha"
* @param cell lowercase-and-underscores cell name within the specifier
* at "pha" index "idx"
* @return the cell's value
*/
#define DT_PHA_BY_IDX(node_id, pha, idx, cell) \
DT_PROP(node_id, pha##_IDX_##idx##_VAL_##cell)
/**
* @brief Like DT_PHA_BY_IDX(), but with a fallback to default_value.
*
* If the value exists, this expands to DT_PHA_BY_IDX(node_id, pha,
* idx, cell). The default_value parameter is not expanded in this
* case.
*
* Otherwise, this expands to default_value.
*
* @param node_id node identifier
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param idx logical index into "pha"
* @param cell lowercase-and-underscores cell name within the specifier
* at "pha" index "idx"
* @param default_value a fallback value to expand to
* @return the cell's value or "default_value"
*/
#define DT_PHA_BY_IDX_OR(node_id, pha, idx, cell, default_value) \
DT_PROP_OR(node_id, pha##_IDX_##idx##_VAL_##cell, default_value)
/* Implementation note: the _IDX_##idx##_VAL_##cell##_EXISTS
* macros are defined, so it's safe to use DT_PROP_OR() here, because
* that uses an IS_ENABLED() on the _EXISTS macro.
*/
/**
* @brief Equivalent to DT_PHA_BY_IDX(node_id, pha, 0, cell)
* @param node_id node identifier
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param cell lowercase-and-underscores cell name
* @return the cell's value
*/
#define DT_PHA(node_id, pha, cell) DT_PHA_BY_IDX(node_id, pha, 0, cell)
/**
* @brief Like DT_PHA(), but with a fallback to default_value
*
* If the value exists, this expands to DT_PHA(node_id, pha, cell).
* The default_value parameter is not expanded in this case.
*
* Otherwise, this expands to default_value.
*
* @param node_id node identifier
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param cell lowercase-and-underscores cell name
* @param default_value a fallback value to expand to
* @return the cell's value or default_value
*/
#define DT_PHA_OR(node_id, pha, cell, default_value) \
DT_PHA_BY_IDX_OR(node_id, pha, 0, cell, default_value)
/**
* @brief Get a value within a phandle-array specifier by name
*
* This is like DT_PHA_BY_IDX(), except it treats "pha" as a structure
* where each array element has a name.
*
* It might help to read the argument order as being similar to
* "node->phandle_struct.name.cell". That is, the cell value is in the
* "pha" property of "node_id", treated as a data structure where
* each array element has a name.
*
* Example devicetree fragment:
*
* n: node {
* io-channels = <&adc1 10>, <&adc2 20>;
* io-channel-names = "SENSOR", "BANDGAP";
* };
*
* Bindings fragment for the "adc1" and "adc2" nodes:
*
* io-channel-cells:
* - input
*
* Example usage:
*
* DT_PHA_BY_NAME(DT_NODELABEL(n), io_channels, sensor, input) // 10
* DT_PHA_BY_NAME(DT_NODELABEL(n), io_channels, bandgap, input) // 20
*
* @param node_id node identifier
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param name lowercase-and-underscores name of a specifier in "pha"
* @param cell lowercase-and-underscores cell name in the named specifier
* @return the cell's value
*/
#define DT_PHA_BY_NAME(node_id, pha, name, cell) \
DT_PROP(node_id, pha##_NAME_##name##_VAL_##cell)
/**
* @brief Like DT_PHA_BY_NAME(), but with a fallback to default_value
*
* If the value exists, this expands to DT_PHA_BY_NAME(node_id, pha,
* name, cell). The default_value parameter is not expanded in this case.
*
* Otherwise, this expands to default_value.
*
* @param node_id node identifier
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param name lowercase-and-underscores name of a specifier in "pha"
* @param cell lowercase-and-underscores cell name in the named specifier
* @param default_value a fallback value to expand to
* @return the cell's value or default_value
*/
#define DT_PHA_BY_NAME_OR(node_id, pha, name, cell, default_value) \
DT_PROP_OR(node_id, pha##_NAME_##name##_VAL_##cell, default_value)
/* Implementation note: the _NAME_##name##_VAL_##cell##_EXISTS
* macros are defined, so it's safe to use DT_PROP_OR() here, because
* that uses an IS_ENABLED() on the _EXISTS macro.
*/
/**
* @brief Get a phandle's node identifier from a phandle array by name
*
* It might help to read the argument order as being similar to
* "node->phandle_struct.name.phandle". That is, the phandle array is
* treated as a structure with named elements. The return value is
* the node identifier for a phandle inside the structure.
*
* Example devicetree fragment:
*
* adc1: adc@... {
* label = "ADC_1";
* };
*
* adc2: adc@... {
* label = "ADC_2";
* };
*
* n: node {
* io-channels = <&adc1 10>, <&adc2 20>;
* io-channel-names = "SENSOR", "BANDGAP";
* };
*
* Above, "io-channels" has two elements:
*
* - the element named "SENSOR" has phandle &adc1
* - the element named "BANDGAP" has phandle &adc2
*
* Example usage:
*
* #define NODE DT_NODELABEL(n)
*
* DT_LABEL(DT_PHANDLE_BY_NAME(NODE, io_channels, sensor)) // "ADC_1"
* DT_LABEL(DT_PHANDLE_BY_NAME(NODE, io_channels, bandgap)) // "ADC_2"
*
* Notice how devicetree properties and names are lowercased, and
* non-alphanumeric characters are converted to underscores.
*
* @param node_id node identifier
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param name lowercase-and-underscores name of an element in "pha"
* @return a node identifier for the node with that phandle
*/
#define DT_PHANDLE_BY_NAME(node_id, pha, name) \
DT_PROP(node_id, pha##_NAME_##name##_PH)
/**
* @brief Get a node identifier for a phandle in a property.
*
* When a node's value at a logical index contains a phandle, this
* macro returns a node identifier for the node with that phandle.
*
* Therefore, if "prop" has type "phandle", "idx" must be zero. (A
* "phandle" type is treated as a "phandles" with a fixed length of
* 1).
*
* Example devicetree fragment:
*
* n1: node-1 {
* foo = <&n2 &n3>;
* };
*
* n2: node-2 { ... };
* n3: node-3 { ... };
*
* Above, "foo" has type phandles and has two elements:
*
* - index 0 has phandle &n2, which is node-2's phandle
* - index 1 has phandle &n3, which is node-3's phandle
*
* Example usage:
*
* #define N1 DT_NODELABEL(n1)
*
* DT_PHANDLE_BY_IDX(N1, foo, 0) // node identifier for node-2
* DT_PHANDLE_BY_IDX(N1, foo, 1) // node identifier for node-3
*
* Behavior is analogous for phandle-arrays.
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property name in "node_id"
* with type "phandle", "phandles" or "phandle-array"
* @param idx index into "prop"
* @return node identifier for the node with the phandle at that index
*/
#define DT_PHANDLE_BY_IDX(node_id, prop, idx) \
DT_PROP(node_id, prop##_IDX_##idx##_PH)
/**
* @brief Get a node identifier for a phandle property's value
*
* This is equivalent to DT_PHANDLE_BY_IDX(node_id, prop, 0). Its primary
* benefit is readability when "prop" has type "phandle".
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property of "node_id"
* with type "phandle"
* @return a node identifier for the node pointed to by "ph"
*/
#define DT_PHANDLE(node_id, prop) DT_PHANDLE_BY_IDX(node_id, prop, 0)
/**
* @}
*/
/**
* @defgroup devicetree-reg-prop reg property
* @ingroup devicetree
* @{
*/
/**
* @brief Get the number of register blocks in the reg property
*
* Use this instead of DT_PROP_LEN(node_id, reg).
* @param node_id node identifier
* @return Number of register blocks in the node's "reg" property.
*/
#define DT_NUM_REGS(node_id) DT_CAT(node_id, _REG_NUM)
/**
* @brief Is "idx" a valid register block index?
*
* If this returns 1, then DT_REG_ADDR_BY_IDX(node_id, idx) or
* DT_REG_SIZE_BY_IDX(node_id, idx) are valid.
* If it returns 0, it is an error to use those macros with index "idx".
* @param node_id node identifier
* @param idx index to check
* @return 1 if "idx" is a valid register block index,
* 0 otherwise.
*/
#define DT_REG_HAS_IDX(node_id, idx) \
IS_ENABLED(DT_CAT(node_id, _REG_IDX_##idx##_EXISTS))
/**
* @brief Get the base address of the register block at index "idx"
* @param node_id node identifier
* @param idx index of the register whose address to return
* @return address of the idx-th register block
*/
#define DT_REG_ADDR_BY_IDX(node_id, idx) \
DT_CAT(node_id, _REG_IDX_##idx##_VAL_ADDRESS)
/**
* @brief Get the size of the register block at index "idx"
*
* This is the size of an individual register block, not the total
* number of register blocks in the property; use DT_NUM_REGS() for
* that.
*
* @param node_id node identifier
* @param idx index of the register whose size to return
* @return size of the idx-th register block
*/
#define DT_REG_SIZE_BY_IDX(node_id, idx) \
DT_CAT(node_id, _REG_IDX_##idx##_VAL_SIZE)
/**
* @brief Get a node's (only) register block address
*
* Equivalent to DT_REG_ADDR_BY_IDX(node_id, 0).
* @param node_id node identifier
* @return node's register block address
*/
#define DT_REG_ADDR(node_id) DT_REG_ADDR_BY_IDX(node_id, 0)
/**
* @brief Get a node's (only) register block size
*
* Equivalent to DT_REG_SIZE_BY_IDX(node_id, 0).
* @param node_id node identifier
* @return node's only register block's size
*/
#define DT_REG_SIZE(node_id) DT_REG_SIZE_BY_IDX(node_id, 0)
/**
* @brief Get a register block's base address by name
* @param node_id node identifier
* @param name lowercase-and-underscores register specifier name
* @return address of the register block specified by name
*/
#define DT_REG_ADDR_BY_NAME(node_id, name) \
DT_CAT(node_id, _REG_NAME_##name##_VAL_ADDRESS)
/**
* @brief Get a register block's size by name
* @param node_id node identifier
* @param name lowercase-and-underscores register specifier name
* @return size of the register block specified by name
*/
#define DT_REG_SIZE_BY_NAME(node_id, name) \
DT_CAT(node_id, _REG_NAME_##name##_VAL_SIZE)
/**
* @}
*/
/**
* @defgroup devicetree-interrupts-prop interrupts property
* @ingroup devicetree
* @{
*/
/**
* @brief Get the number of interrupt sources for the node
*
* Use this instead of DT_PROP_LEN(node_id, interrupts).
*
* @param node_id node identifier
* @return Number of interrupt specifiers in the node's "interrupts" property.
*/
#define DT_NUM_IRQS(node_id) DT_CAT(node_id, _IRQ_NUM)
/**
* @brief Is "idx" a valid interrupt index?
*
* If this returns 1, then DT_IRQ_BY_IDX(node_id, idx) is valid.
* If it returns 0, it is an error to use that macro with this index.
* @param node_id node identifier
* @param idx index to check
* @return 1 if the idx is valid for the interrupt property
* 0 otherwise.
*/
#define DT_IRQ_HAS_IDX(node_id, idx) \
IS_ENABLED(DT_CAT(node_id, _IRQ_IDX_##idx##_EXISTS))
/**
* @brief Does an interrupts property have a named cell specifier at an index?
* If this returns 1, then DT_IRQ_BY_IDX(node_id, idx, cell) is valid.
* If it returns 0, it is an error to use that macro.
* @param node_id node identifier
* @param idx index to check
* @param cell named cell value whose existence to check
* @return 1 if the named cell exists in the interrupt specifier at index idx
* 0 otherwise.
*/
#define DT_IRQ_HAS_CELL_AT_IDX(node_id, idx, cell) \
IS_ENABLED(DT_CAT(node_id, _IRQ_IDX_##idx##_VAL_##cell##_EXISTS))
/**
* @brief Equivalent to DT_IRQ_HAS_CELL_AT_IDX(node_id, 0, cell)
* @param node_id node identifier
* @param cell named cell value whose existence to check
* @return 1 if the named cell exists in the interrupt specifier at index 0
* 0 otherwise.
*/
#define DT_IRQ_HAS_CELL(node_id, cell) DT_IRQ_HAS_CELL_AT_IDX(node_id, 0, cell)
/**
* @brief Does an interrupts property have a named specifier value at an index?
* If this returns 1, then DT_IRQ_BY_NAME(node_id, name, cell) is valid.
* If it returns 0, it is an error to use that macro.
* @param node_id node identifier
* @param name lowercase-and-underscores interrupt specifier name
* @return 1 if "name" is a valid named specifier
* 0 otherwise.
*/
#define DT_IRQ_HAS_NAME(node_id, name) \
IS_ENABLED(DT_CAT(node_id, _IRQ_NAME_##name##_VAL_irq_EXISTS))
/**
* @brief Get a value within an interrupt specifier at an index
*
* It might help to read the argument order as being similar to
* "node->interrupts[index].cell".
*
* This can be used to get information about an individual interrupt
* when a device generates more than one.
*
* Example devicetree fragment:
*
* my-serial: serial@... {
* interrupts = < 33 0 >, < 34 1 >;
* };
*
* Assuming the node's interrupt domain has "#interrupt-cells = <2>;" and
* the individual cells in each interrupt specifier are named "irq" and
* "priority" by the node's binding, here are some examples:
*
* #define SERIAL DT_NODELABEL(my_serial)
*
* Example usage Value
* ------------- -----
* DT_IRQ_BY_IDX(SERIAL, 0, irq) 33
* DT_IRQ_BY_IDX(SERIAL, 0, priority) 0
* DT_IRQ_BY_IDX(SERIAL, 1, irq, 34
* DT_IRQ_BY_IDX(SERIAL, 1, priority) 1
*
* @param node_id node identifier
* @param idx logical index into the interrupt specifier array
* @param cell cell name specifier
* @return the named value at the specifier given by the index
*/
#define DT_IRQ_BY_IDX(node_id, idx, cell) \
DT_CAT(node_id, _IRQ_IDX_##idx##_VAL_##cell)
/**
* @brief Get a value within an interrupt specifier by name
*
* It might help to read the argument order as being similar to
* "node->interrupts.name.cell".
*
* This can be used to get information about an individual interrupt
* when a device generates more than one, if the bindings give each
* interrupt specifier a name.
*
* @param node_id node identifier
* @param name lowercase-and-underscores interrupt specifier name
* @param cell cell name specifier
* @return the named value at the specifier given by the index
*/
#define DT_IRQ_BY_NAME(node_id, name, cell) \
DT_CAT(node_id, _IRQ_NAME_##name##_VAL_##cell)
/**
* @brief Get an interrupt specifier's value
* Equivalent to DT_IRQ_BY_IDX(node_id, 0, cell).
* @param node_id node identifier
* @param cell cell name specifier
* @return the named value at that index
*/
#define DT_IRQ(node_id, cell) DT_IRQ_BY_IDX(node_id, 0, cell)
/**
* @brief Get a node's (only) irq number
*
* Equivalent to DT_IRQ(node_id, irq). This is provided as a convenience
* for the common case where a node generates exactly one interrupt,
* and the IRQ number is in a cell named "irq".
*
* @param node_id node identifier
* @return the interrupt number for the node's only interrupt
*/
#define DT_IRQN(node_id) DT_IRQ(node_id, irq)
/**
* @}
*/
/**
* @defgroup devicetree-generic-chosen Chosen nodes
* @ingroup devicetree
* @{
*/
/**
* @brief Get a node identifier for a /chosen node property
*
* This is only valid to call if DT_HAS_CHOSEN(prop) is 1.
* @param prop lowercase-and-underscores property name for
* the /chosen node
* @return a node identifier for the chosen node property
*/
#define DT_CHOSEN(prop) DT_CAT(DT_CHOSEN_, prop)
/**
* @brief Test if the devicetree has a /chosen node
* @param prop lowercase-and-underscores devicetree property
* @return 1 if the chosen property exists and refers to a node,
* 0 otherwise
*/
#define DT_HAS_CHOSEN(prop) IS_ENABLED(DT_CHOSEN_##prop##_EXISTS)
/**
* @}
*/
/**
* @defgroup devicetree-generic-foreach "For-each" macros
* @ingroup devicetree
* @{
*/
/**
* @brief Invokes "fn" for each child of "node_id"
*
* The macro "fn" must take one parameter, which will be the node
* identifier of a child node of "node_id".
*
* Example devicetree fragment:
*
* n: node {
* child-1 {
* label = "foo";
* };
* child-2 {
* label = "bar";
* };
* };
*
* Example usage:
*
* #define LABEL_AND_COMMA(node_id) DT_LABEL(node_id),
*
* const char *child_labels[] = {
* DT_FOREACH_CHILD(DT_NODELABEL(n), LABEL_AND_COMMA)
* };
*
* This expands to:
*
* const char *child_labels[] = {
* "foo", "bar",
* };
*
* @param node_id node identifier
* @param fn macro to invoke
*/
#define DT_FOREACH_CHILD(node_id, fn) \
DT_CAT(node_id, _FOREACH_CHILD)(fn)
/**
* @}
*/
/**
* @defgroup devicetree-generic-exist Existence checks
* @ingroup devicetree
* @{
*/
/**
* @brief Does a node identifier refer to a node?
*
* Tests whether a node identifier refers to a node which exists, i.e.
* is defined in the devicetree.
*
* It doesn't matter whether or not the node has a matching binding,
* or what the node's status value is. This is purely a check of
* whether the node exists at all.
*
* @param node_id a node identifier
* @return 1 if the node identifier refers to a node,
* 0 otherwise.
*/
#define DT_NODE_EXISTS(node_id) IS_ENABLED(DT_CAT(node_id, _EXISTS))
/**
* @brief Does a node identifier refer to a node with a status?
*
* Example uses:
*
* DT_NODE_HAS_STATUS(DT_PATH(soc, i2c_12340000), okay)
* DT_NODE_HAS_STATUS(DT_PATH(soc, i2c_12340000), disabled)
*
* Tests whether a node identifier refers to a node which:
*
* - exists in the devicetree, and
* - has a status property matching the second argument
* (except that either a missing status or an "ok" status
* in the devicetree is treated as if it were "okay" instead)
*
* @param node_id a node identifier
* @param status a status as one of the tokens okay or disabled, not a string
* @return 1 if the node has the given status, 0 otherwise.
*/
#define DT_NODE_HAS_STATUS(node_id, status) \
DT_NODE_HAS_STATUS_INTERNAL(node_id, status)
/**
* @brief Does the devicetree have a status "okay" node with a compatible?
*
* Test for whether the devicetree has any nodes with status "okay"
* and the given compatible. That is, this returns 1 if and only if
* there is at least one "node_id" for which both of these
* expressions return 1:
*
* DT_NODE_HAS_STATUS(node_id, okay)
* DT_NODE_HAS_COMPAT(node_id, compat)
*
* As usual, both a missing status and an "ok" status are treated as
* "okay".
*
* @param compat lowercase-and-underscores version of a compatible
* @return 1 if both of the above conditions are met, 0 otherwise
*/
#define DT_HAS_COMPAT_STATUS_OKAY(compat) \
IS_ENABLED(DT_CAT(DT_COMPAT_HAS_OKAY_, compat))
/**
* @brief Get the number of instances of a given compatible with
* status "okay"
* @param compat lowercase-and-underscores version of a compatible
* @return Number of instances with status "okay"
*/
#define DT_NUM_INST_STATUS_OKAY(compat) \
UTIL_AND(DT_HAS_COMPAT_STATUS_OKAY(compat), \
UTIL_CAT(DT_N_INST, DT_DASH(compat, NUM_OKAY)))
/**
* @brief Does a devicetree node match a compatible?
*
* Example devicetree fragment:
*
* n: node {
* compatible = "vnd,specific-device", "generic-device";
* }
*
* Example usages which evaluate to 1:
*
* DT_NODE_HAS_COMPAT(DT_NODELABEL(n), vnd_specific_device)
* DT_NODE_HAS_COMPAT(DT_NODELABEL(n), generic_device)
*
* This macro only uses the value of the compatible property. Whether
* or not a particular compatible has a matching binding has no effect
* on its value, nor does the node's status.
*
* @param node_id node identifier
* @param compat lowercase-and-underscorse compatible value
* @return 1 if the node's compatible property contains compat,
* 0 otherwise.
*/
#define DT_NODE_HAS_COMPAT(node_id, compat) \
IS_ENABLED(DT_CAT(node_id, _COMPAT_MATCHES_##compat))
/**
* @brief Does a devicetree node have a compatible and status?
*
* This is equivalent to:
*
* (DT_NODE_HAS_COMPAT(node_id, compat) &&
* DT_NODE_HAS_STATUS(node_id, status))
*
* @param node_id node identifier
* @param compat lowercase-and-underscores compatible
* @param status okay or disabled as a token, not a string
*/
#define DT_NODE_HAS_COMPAT_STATUS(node_id, compat, status) \
DT_NODE_HAS_COMPAT(node_id, compat) && DT_NODE_HAS_STATUS(node_id, status)
/**
* @brief Does a devicetree node have a property?
*
* Tests whether a devicetree node has a property defined.
*
* This tests whether the property is defined at all, not whether a
* boolean property is true or false. To get a boolean property's
* truth value, use DT_PROP(node_id, prop) instead.
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property name
* @return 1 if the node has the property, 0 otherwise.
*/
#define DT_NODE_HAS_PROP(node_id, prop) \
IS_ENABLED(DT_CAT(node_id, _P_##prop##_EXISTS))
/**
* @brief Does a phandle array have a named cell specifier at an index?
*
* If this returns 1, then the phandle-array property "pha" has a cell
* named "cell" at index "idx", and therefore DT_PHA_BY_IDX(node_id,
* pha, idx, cell) is valid. If it returns 0, it's an error to use
* DT_PHA_BY_IDX() with the same arguments.
*
* @param node_id node identifier
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param idx index to check within "pha"
* @param cell lowercase-and-underscores cell name whose existence to check
* at index "idx"
* @return 1 if the named cell exists in the specifier at index idx,
* 0 otherwise.
*/
#define DT_PHA_HAS_CELL_AT_IDX(node_id, pha, idx, cell) \
IS_ENABLED(DT_PROP(node_id, \
pha##_IDX_##idx##_VAL_##cell##_EXISTS))
/**
* @brief Equivalent to DT_PHA_HAS_CELL_AT_IDX(node_id, pha, 0, cell)
* @param node_id node identifier
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param cell lowercase-and-underscores cell name whose existence to check
* at index "idx"
* @return 1 if the named cell exists in the specifier at index 0,
* 0 otherwise.
*/
#define DT_PHA_HAS_CELL(node_id, pha, cell) \
DT_PHA_HAS_CELL_AT_IDX(node_id, pha, 0, cell)
/**
* @}
*/
/**
* @defgroup devicetree-generic-bus Bus helpers
* @ingroup devicetree
* @{
*/
/**
* @brief Node's bus controller
*
* Get the node identifier of the node's bus controller. This can be
* used with @ref DT_PROP() to get properties of the bus controller.
*
* It is an error to use this with nodes which do not have bus
* controllers.
*
* Example devicetree fragment:
*
* i2c@deadbeef {
* label = "I2C_CTLR";
* status = "okay";
* clock-frequency = < 100000 >;
*
* i2c_device: accelerometer@12 {
* ...
* };
* };
*
* Example usage:
*
* DT_PROP(DT_BUS(DT_NODELABEL(i2c_device)), clock_frequency) // 100000
*
* @param node_id node identifier
* @return a node identifier for the node's bus controller
*/
#define DT_BUS(node_id) DT_CAT(node_id, _BUS)
/**
* @brief Node's bus controller's label property
* @param node_id node identifier
* @return the label property of the node's bus controller DT_BUS(node)
*/
#define DT_BUS_LABEL(node_id) DT_PROP(DT_BUS(node_id), label)
/**
* @brief Is a node on a bus of a given type?
*
* Example devicetree overlay:
*
* &i2c0 {
* temp: temperature-sensor@76 {
* compatible = "vnd,some-sensor";
* reg = <0x76>;
* };
* };
*
* Example usage, assuming "i2c0" is an I2C bus controller node, and
* therefore "temp" is on an I2C bus:
*
* DT_ON_BUS(DT_NODELABEL(temp), i2c) // 1
* DT_ON_BUS(DT_NODELABEL(temp), spi) // 0
*
* @param node_id node identifier
* @param bus lowercase-and-underscores bus type as a C token (i.e.
* without quotes)
* @return 1 if the node is on a bus of the given type,
* 0 otherwise
*/
#define DT_ON_BUS(node_id, bus) IS_ENABLED(DT_CAT(node_id, _BUS_##bus))
/**
* @}
*/
/**
* @defgroup devicetree-inst Instance-based devicetree APIs
* @ingroup devicetree
* @{
*/
/**
* @brief Node identifier for an instance of a DT_DRV_COMPAT compatible
* @param inst instance number
* @return a node identifier for the node with DT_DRV_COMPAT compatible and
* instance number "inst"
*/
#define DT_DRV_INST(inst) DT_INST(inst, DT_DRV_COMPAT)
/**
* @brief Call "fn" on all child nodes of DT_DRV_INST(inst).
*
* The macro "fn" should take one argument, which is the node
* identifier for the child node.
*
* @param inst instance number
* @param fn macro to invoke on each child node identifier
*
* @see DT_FOREACH_CHILD
*/
#define DT_INST_FOREACH_CHILD(inst, fn) \
DT_FOREACH_CHILD(DT_DRV_INST(inst), fn)
/**
* @brief Get a DT_DRV_COMPAT instance property
* @param inst instance number
* @param prop lowercase-and-underscores property name
* @return a representation of the property's value
*/
#define DT_INST_PROP(inst, prop) DT_PROP(DT_DRV_INST(inst), prop)
/**
* @brief Get a DT_DRV_COMPAT property length
* @param inst instance number
* @param prop lowercase-and-underscores property name
* @return logical length of the property
*/
#define DT_INST_PROP_LEN(inst, prop) DT_PROP_LEN(DT_DRV_INST(inst), prop)
/**
* @brief Is index "idx" valid for an array type property
* on a DT_DRV_COMPAT instance?
* @param inst instance number
* @param prop lowercase-and-underscores property name
* @param idx index to check
* @return 1 if "idx" is a valid index into the given property,
* 0 otherwise.
*/
#define DT_INST_PROP_HAS_IDX(inst, prop, idx) \
DT_PROP_HAS_IDX(DT_DRV_INST(inst), prop, idx)
/**
* @brief Get a DT_DRV_COMPAT element value in an array property
* @param inst instance number
* @param prop lowercase-and-underscores property name
* @param idx the index to get
* @return a representation of the idx-th element of the property
*/
#define DT_INST_PROP_BY_IDX(inst, prop, idx) \
DT_PROP_BY_IDX(DT_DRV_INST(inst), prop, idx)
/**
* @brief Like DT_INST_PROP(), but with a fallback to default_value
* @param inst instance number
* @param prop lowercase-and-underscores property name
* @param default_value a fallback value to expand to
* @return DT_INST_PROP(inst, prop) or default_value
*/
#define DT_INST_PROP_OR(inst, prop, default_value) \
DT_PROP_OR(DT_DRV_INST(inst), prop, default_value)
/**
* @brief Get a DT_DRV_COMPAT instance's "label" property
* @param inst instance number
* @return instance's label property value
*/
#define DT_INST_LABEL(inst) DT_INST_PROP(inst, label)
/**
* @brief Get a DT_DRV_COMPAT instance's property value from a phandle's node
* @param inst instance number
* @param ph lowercase-and-underscores property of "inst"
* with type "phandle"
* @param prop lowercase-and-underscores property of the phandle's node
* @return the value of "prop" as described in the DT_PROP() documentation
*/
#define DT_INST_PROP_BY_PHANDLE(inst, ph, prop) \
DT_INST_PROP_BY_PHANDLE_IDX(inst, ph, 0, prop)
/**
* @brief Get a DT_DRV_COMPAT instance's property value from a phandle in a
* property.
* @param inst instance number
* @param phs lowercase-and-underscores property with type "phandle",
* "phandles", or "phandle-array"
* @param idx logical index into "phs", which must be zero if "phs"
* has type "phandle"
* @param prop lowercase-and-underscores property of the phandle's node
* @return the value of "prop" as described in the DT_PROP() documentation
*/
#define DT_INST_PROP_BY_PHANDLE_IDX(inst, phs, idx, prop) \
DT_PROP_BY_PHANDLE_IDX(DT_DRV_INST(inst), phs, idx, prop)
/**
* @brief Get a DT_DRV_COMPAT instance's phandle-array specifier value at an index
* @param inst instance number
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param idx logical index into the property "pha"
* @param cell binding's cell name within the specifier at index "idx"
* @return the value of the cell inside the specifier at index "idx"
*/
#define DT_INST_PHA_BY_IDX(inst, pha, idx, cell) \
DT_PHA_BY_IDX(DT_DRV_INST(inst), pha, idx, cell)
/**
* @brief Like DT_INST_PHA_BY_IDX(), but with a fallback to default_value
* @param inst instance number
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param idx logical index into the property "pha"
* @param cell binding's cell name within the specifier at index "idx"
* @param default_value a fallback value to expand to
* @return DT_INST_PHA_BY_IDX(inst, pha, idx, cell) or default_value
*/
#define DT_INST_PHA_BY_IDX_OR(inst, pha, idx, cell, default_value) \
DT_PHA_BY_IDX_OR(DT_DRV_INST(inst), pha, idx, cell, default_value)
/**
* @brief Get a DT_DRV_COMPAT instance's phandle-array specifier value
* Equivalent to DT_INST_PHA_BY_IDX(inst, pha, 0, cell)
* @param inst instance number
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param cell binding's cell name for the specifier at "pha" index 0
* @return the cell value
*/
#define DT_INST_PHA(inst, pha, cell) DT_INST_PHA_BY_IDX(inst, pha, 0, cell)
/**
* @brief Like DT_INST_PHA(), but with a fallback to default_value
* @param inst instance number
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param cell binding's cell name for the specifier at "pha" index 0
* @param default_value a fallback value to expand to
* @return DT_INST_PHA(inst, pha, cell) or default_value
*/
#define DT_INST_PHA_OR(inst, pha, cell, default_value) \
DT_INST_PHA_BY_IDX_OR(inst, pha, 0, cell, default_value)
/**
* @brief Get a DT_DRV_COMPAT instance's value within a phandle-array
* specifier by name
* @param inst instance number
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param name lowercase-and-underscores name of a specifier in "pha"
* @param cell binding's cell name for the named specifier
* @return the cell value
*/
#define DT_INST_PHA_BY_NAME(inst, pha, name, cell) \
DT_PHA_BY_NAME(DT_DRV_INST(inst), pha, name, cell)
/**
* @brief Like DT_INST_PHA_BY_NAME(), but with a fallback to default_value
* @param inst instance number
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param name lowercase-and-underscores name of a specifier in "pha"
* @param cell binding's cell name for the named specifier
* @param default_value a fallback value to expand to
* @return DT_INST_PHA_BY_NAME(inst, pha, name, cell) or default_value
*/
#define DT_INST_PHA_BY_NAME_OR(inst, pha, name, cell, default_value) \
DT_PHA_BY_NAME_OR(DT_DRV_INST(inst), pha, name, cell, default_value)
/**
* @brief Get a DT_DRV_COMPAT instance's phandle node identifier from a
* phandle array by name
* @param inst instance number
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param name lowercase-and-underscores name of an element in "pha"
* @return node identifier for the phandle at the element named "name"
*/
#define DT_INST_PHANDLE_BY_NAME(inst, pha, name) \
DT_PHANDLE_BY_NAME(DT_DRV_INST(inst), pha, name) \
/**
* @brief Get a DT_DRV_COMPAT instance's node identifier for a phandle in
* a property.
* @param inst instance number
* @param prop lowercase-and-underscores property name in "inst"
* with type "phandle", "phandles" or "phandle-array"
* @param idx index into "prop"
* @return a node identifier for the phandle at index "idx" in "prop"
*/
#define DT_INST_PHANDLE_BY_IDX(inst, prop, idx) \
DT_PHANDLE_BY_IDX(DT_DRV_INST(inst), prop, idx)
/**
* @brief Get a DT_DRV_COMPAT instance's node identifier for a phandle
* property's value
* @param inst instance number
* @param prop lowercase-and-underscores property of "inst"
* with type "phandle"
* @return a node identifier for the node pointed to by "ph"
*/
#define DT_INST_PHANDLE(inst, prop) DT_INST_PHANDLE_BY_IDX(inst, prop, 0)
/**
* @brief is "idx" a valid register block index on a DT_DRV_COMPAT instance?
* @param inst instance number
* @param idx index to check
* @return 1 if "idx" is a valid register block index,
* 0 otherwise.
*/
#define DT_INST_REG_HAS_IDX(inst, idx) DT_REG_HAS_IDX(DT_DRV_INST(inst), idx)
/**
* @brief Get a DT_DRV_COMPAT instance's idx-th register block's address
* @param inst instance number
* @param idx index of the register whose address to return
* @return address of the instance's idx-th register block
*/
#define DT_INST_REG_ADDR_BY_IDX(inst, idx) DT_REG_ADDR_BY_IDX(DT_DRV_INST(inst), idx)
/**
* @brief Get a DT_DRV_COMPAT instance's idx-th register block's size
* @param inst instance number
* @param idx index of the register whose size to return
* @return size of the instance's idx-th register block
*/
#define DT_INST_REG_SIZE_BY_IDX(inst, idx) \
DT_REG_SIZE_BY_IDX(DT_DRV_INST(inst), idx)
/**
* @brief Get a DT_DRV_COMPAT's register block address by name
* @param inst instance number
* @param name lowercase-and-underscores register specifier name
* @return address of the register block with the given name
*/
#define DT_INST_REG_ADDR_BY_NAME(inst, name) \
DT_REG_ADDR_BY_NAME(DT_DRV_INST(inst), name)
/**
* @brief Get a DT_DRV_COMPAT's register block size by name
* @param inst instance number
* @param name lowercase-and-underscores register specifier name
* @return size of the register block with the given name
*/
#define DT_INST_REG_SIZE_BY_NAME(inst, name) \
DT_REG_SIZE_BY_NAME(DT_DRV_INST(inst), name)
/**
* @brief Get a DT_DRV_COMPAT's (only) register block address
* @param inst instance number
* @return instance's register block address
*/
#define DT_INST_REG_ADDR(inst) DT_INST_REG_ADDR_BY_IDX(inst, 0)
/**
* @brief Get a DT_DRV_COMPAT's (only) register block size
* @param inst instance number
* @return instance's register block size
*/
#define DT_INST_REG_SIZE(inst) DT_INST_REG_SIZE_BY_IDX(inst, 0)
/**
* @brief Get a DT_DRV_COMPAT interrupt specifier value at an index
* @param inst instance number
* @param idx logical index into the interrupt specifier array
* @param cell cell name specifier
* @return the named value at the specifier given by the index
*/
#define DT_INST_IRQ_BY_IDX(inst, idx, cell) \
DT_IRQ_BY_IDX(DT_DRV_INST(inst), idx, cell)
/**
* @brief Get a DT_DRV_COMPAT interrupt specifier value by name
* @param inst instance number
* @param name lowercase-and-underscores interrupt specifier name
* @param cell cell name specifier
* @return the named value at the specifier given by the index
*/
#define DT_INST_IRQ_BY_NAME(inst, name, cell) \
DT_IRQ_BY_NAME(DT_DRV_INST(inst), name, cell)
/**
* @brief Get a DT_DRV_COMPAT interrupt specifier's value
* @param inst instance number
* @param cell cell name specifier
* @return the named value at that index
*/
#define DT_INST_IRQ(inst, cell) DT_INST_IRQ_BY_IDX(inst, 0, cell)
/**
* @brief Get a DT_DRV_COMPAT's (only) irq number
* @param inst instance number
* @return the interrupt number for the node's only interrupt
*/
#define DT_INST_IRQN(inst) DT_INST_IRQ(inst, irq)
/**
* @brief Get a DT_DRV_COMPAT's bus node's label property
* @param inst instance number
* @return the label property of the instance's bus controller
*/
#define DT_INST_BUS_LABEL(inst) DT_BUS_LABEL(DT_DRV_INST(inst))
/**
* @brief Test if a DT_DRV_COMPAT's bus type is a given type
* @param inst instance number
* @param bus a binding's bus type as a C token, lowercased and without quotes
* @return 1 if the given instance is on a bus of the given type,
* 0 otherwise
*/
#define DT_INST_ON_BUS(inst, bus) DT_ON_BUS(DT_DRV_INST(inst), bus)
/**
* @brief Test if any DT_DRV_COMPAT node is on a bus of a given type
* and has status okay
*
* This is a special-purpose macro which can be useful when writing
* drivers for devices which can appear on multiple buses. One example
* is a sensor device which may be wired on an I2C or SPI bus.
*
* Example devicetree overlay:
*
* &i2c0 {
* temp: temperature-sensor@76 {
* compatible = "vnd,some-sensor";
* reg = <0x76>;
* };
* };
*
* Example usage, assuming "i2c0" is an I2C bus controller node, and
* therefore "temp" is on an I2C bus:
*
* #define DT_DRV_COMPAT vnd_some_sensor
*
* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) // 1
*
* @param bus a binding's bus type as a C token, lowercased and without quotes
* @return 1 if any enabled node with that compatible is on that bus type,
* 0 otherwise
*/
#define DT_ANY_INST_ON_BUS_STATUS_OKAY(bus) \
DT_COMPAT_ON_BUS_INTERNAL(DT_DRV_COMPAT, bus)
/**
* @brief Call "fn" on all nodes with compatible DT_DRV_COMPAT
* and status "okay"
*
* This macro calls "fn(inst)" on each "inst" number that refers to a
* node with status "okay". Whitespace is added between invocations.
*
* Example devicetree fragment:
*
* a {
* compatible = "vnd,device";
* status = "okay";
* label = "DEV_A";
* };
*
* b {
* compatible = "vnd,device";
* status = "okay";
* label = "DEV_B";
* };
*
* c {
* compatible = "vnd,device";
* status = "disabled";
* label = "DEV_C";
* };
*
* Example usage:
*
* #define DT_DRV_COMPAT vnd_device
* #define MY_FN(inst) DT_INST_LABEL(inst),
*
* DT_INST_FOREACH_STATUS_OKAY(MY_FN)
*
* This expands to:
*
* MY_FN(0) MY_FN(1)
*
* and from there, to either this:
*
* "DEV_A", "DEV_B",
*
* or this:
*
* "DEV_B", "DEV_A",
*
* No guarantees are made about the order that a and b appear in the
* expansion.
*
* Note that "fn" is responsible for adding commas, semicolons, or
* other separators or terminators.
*
* Device drivers should use this macro whenever possible to
* instantiate a struct device for each enabled node in the devicetree
* of the driver's compatible DT_DRV_COMPAT.
*
* @param fn Macro to call for each enabled node. Must accept an
* instance number as its only parameter.
*/
#define DT_INST_FOREACH_STATUS_OKAY(fn) \
COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT), \
(UTIL_CAT(DT_FOREACH_OKAY_INST_, \
DT_DRV_COMPAT)(fn)), \
())
/**
* @brief Does a DT_DRV_COMPAT instance have a property?
* @param inst instance number
* @param prop lowercase-and-underscores property name
* @return 1 if the instance has the property, 0 otherwise.
*/
#define DT_INST_NODE_HAS_PROP(inst, prop) \
DT_NODE_HAS_PROP(DT_DRV_INST(inst), prop)
/**
* @brief Does a phandle array have a named cell specifier at an index
* for a DT_DRV_COMPAT instance?
* @param inst instance number
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param idx index to check
* @param cell named cell value whose existence to check
* @return 1 if the named cell exists in the specifier at index idx,
* 0 otherwise.
*/
#define DT_INST_PHA_HAS_CELL_AT_IDX(inst, pha, idx, cell) \
DT_PHA_HAS_CELL_AT_IDX(DT_DRV_INST(inst), pha, idx, cell)
/**
* @brief Does a phandle array have a named cell specifier at index 0
* for a DT_DRV_COMPAT instance?
* @param inst instance number
* @param pha lowercase-and-underscores property with type "phandle-array"
* @param cell named cell value whose existence to check
* @return 1 if the named cell exists in the specifier at index 0,
* 0 otherwise.
*/
#define DT_INST_PHA_HAS_CELL(inst, pha, cell) \
DT_INST_PHA_HAS_CELL_AT_IDX(inst, pha, 0, cell)
/**
* @brief is index valid for interrupt property on a DT_DRV_COMPAT instance?
* @param inst instance number
* @param idx logical index into the interrupt specifier array
* @return 1 if the idx is valid for the interrupt property
* 0 otherwise.
*/
#define DT_INST_IRQ_HAS_IDX(inst, idx) DT_IRQ_HAS_IDX(DT_DRV_INST(inst), idx)
/**
* @brief Does a DT_DRV_COMPAT instance have an interrupt named cell specifier?
* @param inst instance number
* @param idx index to check
* @param cell named cell value whose existence to check
* @return 1 if the named cell exists in the interrupt specifier at index idx
* 0 otherwise.
*/
#define DT_INST_IRQ_HAS_CELL_AT_IDX(inst, idx, cell) \
DT_IRQ_HAS_CELL_AT_IDX(DT_DRV_INST(inst), idx, cell)
/**
* @brief Does a DT_DRV_COMPAT instance have an interrupt value?
* @param inst instance number
* @param cell named cell value whose existence to check
* @return 1 if the named cell exists in the interrupt specifier at index 0
* 0 otherwise.
*/
#define DT_INST_IRQ_HAS_CELL(inst, cell) \
DT_INST_IRQ_HAS_CELL_AT_IDX(inst, 0, cell)
/**
* @brief Does a DT_DRV_COMPAT instance have an interrupt value?
* @param inst instance number
* @param name lowercase-and-underscores interrupt specifier name
* @return 1 if "name" is a valid named specifier
*/
#define DT_INST_IRQ_HAS_NAME(inst, name) \
DT_IRQ_HAS_NAME(DT_DRV_INST(inst), name)
/**
* @}
*/
/** @internal pay no attention to the man behind the curtain! */
#define DT_PATH_INTERNAL(...) \
UTIL_CAT(DT_ROOT, MACRO_MAP_CAT(DT_S_PREFIX, __VA_ARGS__))
/** @internal helper for DT_PATH(): prepends _S_ to a node name */
#define DT_S_PREFIX(name) _S_##name
/** @internal concatenation helper, sometimes used to force expansion */
#define DT_CAT(node_id, prop_suffix) node_id##prop_suffix
/** @internal helper for node identifier macros to expand args */
#define DT_DASH(...) MACRO_MAP_CAT(DT_DASH_PREFIX, __VA_ARGS__)
/** @internal helper for DT_DASH(): prepends _ to a name */
#define DT_DASH_PREFIX(name) _##name
/** @internal helper for DT_NODE_HAS_STATUS */
#define DT_NODE_HAS_STATUS_INTERNAL(node_id, status) \
IS_ENABLED(DT_CAT(node_id, _STATUS_ ## status))
/** @internal helper for test cases and DT_ANY_INST_ON_BUS_STATUS_OKAY() */
#define DT_COMPAT_ON_BUS_INTERNAL(compat, bus) \
IS_ENABLED(UTIL_CAT(DT_CAT(DT_COMPAT_, compat), _BUS_##bus))
/* have these last so they have access to all previously defined macros */
#include <devicetree/adc.h>
#include <devicetree/clocks.h>
#include <devicetree/gpio.h>
#include <devicetree/spi.h>
#include <devicetree/dma.h>
#include <devicetree/pwms.h>
#include <devicetree/fixed-partitions.h>
#include <devicetree/zephyr.h>
#endif /* DEVICETREE_H */