Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions doc/build/dts/macros.bnf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; An RFC 7405 ABNF grammar for devicetree macros.

Check warning on line 1 in doc/build/dts/macros.bnf

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

Copyright missing

doc/build/dts/macros.bnf:1 File has no SPDX-FileCopyrightText header, consider adding one.

Check warning on line 1 in doc/build/dts/macros.bnf

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

License missing

doc/build/dts/macros.bnf:1 File has no SPDX-License-Identifier header, consider adding one.
;
; This does *not* cover macros pulled out of DT via Kconfig,
; like CONFIG_SRAM_BASE_ADDRESS, etc. It only describes the
Expand Down Expand Up @@ -77,6 +77,8 @@
; These are used by DT_CHILD_NUM and DT_CHILD_NUM_STATUS_OKAY macros
node-macro =/ %s"DT_N" path-id %s"_CHILD_NUM"
node-macro =/ %s"DT_N" path-id %s"_CHILD_NUM_STATUS_OKAY"
; This is used by DT_CHILD_BY_UNIT_ADDR
node-macro =/ %s"DT_N" path-id %s"_CHILD_UNIT_ADDR_" unit-addr
; These are used internally by DT_FOREACH_CHILD, which iterates over
; each child node.
node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD"
Expand Down Expand Up @@ -394,6 +396,17 @@
alternate-id = ( %s"ALIAS" / %s"NODELABEL" ) dt-name
alternate-id =/ %s"INST_" 1*DIGIT "_" dt-name

; --------------------------------------------------------------------
; unit-addr: a unit address token for child lookup helpers
;
; Children that have a unique unit address get helper macros using either
; decimal or lowercase hexadecimal forms of that address.
unit-addr = 1*DIGIT
unit-addr =/ %s"0x" 1*hexdig-lower

; Lowercase hexadecimal digit.
hexdig-lower = DIGIT / %s"a" / %s"b" / %s"c" / %s"d" / %s"e" / %s"f"

; --------------------------------------------------------------------
; miscellaneous helper definitions

Expand Down
5 changes: 5 additions & 0 deletions doc/releases/release-notes-4.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ New Samples
Same as above, this will also be recomputed at the time of the release.
Just link the sample, further details go in the sample documentation itself.
DeviceTree
**********

* :c:macro:`DT_CHILD_BY_UNIT_ADDR`
* :c:macro:`DT_INST_CHILD_BY_UNIT_ADDR`

Libraries / Subsystems
**********************
Expand Down
3 changes: 3 additions & 0 deletions dts/bindings/test/vnd,child-bindings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ include: [base.yaml]
child-binding:
description: Test child binding
properties:
reg:
type: array
required: true
val:
type: int
required: true
52 changes: 52 additions & 0 deletions include/zephyr/devicetree.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,42 @@
*/
#define DT_CHILD(node_id, child) UTIL_CAT(node_id, DT_S_PREFIX(child))

/**
* @brief Get a node identifier for a child node with a matching unit address
*
* @note Only works for children with unique unit addresses.
*
* Example devicetree fragment:
*
* @code{.dts}
* / {
* soc-label: soc {
* serial1: serial@40001000 {
* status = "okay";
* current-speed = <115200>;
* ...
* };
* };
* };
* @endcode
*
* Example usage with DT_PROP() to get the status of the
* `serial@40001000` node:
*
* @code{.c}
* #define SOC_NODE DT_NODELABEL(soc_label)
* DT_PROP(DT_CHILD_BY_UNIT_ADDR(SOC_NODE, 0x40001000), status) // "okay"
* @endcode
*
* @param node_id node identifier
* @param addr Unit address for the child node. Can be decimal or
* hexadecimal (lowercase and prefixed with 0x)
*
* @return node identifier for the child node with the specified unit address
*/
#define DT_CHILD_BY_UNIT_ADDR(node_id, addr) \
DT_CAT3(node_id, _CHILD_UNIT_ADDR_, addr)

/**
* @brief Get a node identifier for a status `okay` node with a compatible
*
Expand Down Expand Up @@ -4066,6 +4102,22 @@
#define DT_INST_CHILD(inst, child) \
DT_CHILD(DT_DRV_INST(inst), child)

/**
* @brief Get a node identifier for a child node with a matching unit address of DT_DRV_INST(inst)
*
* @note Only works for children with unique unit addresses.
*
* @param inst instance number
* @param addr Unit address for the child node. Can be decimal or
* hexadecimal (lowercase and prefixed with 0x)
*
* @return node identifier for the child node with the specified unit address
*
* @see DT_CHILD_BY_UNIT_ADDR
*/
#define DT_INST_CHILD_BY_UNIT_ADDR(inst, addr) \
DT_CHILD_BY_UNIT_ADDR(DT_DRV_INST(inst), addr)

/**
* @brief Get the number of child nodes of a given node
*
Expand Down
5 changes: 1 addition & 4 deletions include/zephyr/drivers/adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,10 +340,7 @@ struct adc_dt_spec {
}

#define ADC_CHANNEL_DT_NODE(ctlr, input) \
DT_FOREACH_CHILD_VARGS(ctlr, ADC_FOREACH_INPUT, input)

#define ADC_FOREACH_INPUT(node, input) \
IF_ENABLED(IS_EQ(DT_REG_ADDR_RAW(node), input), (node))
DT_CHILD_BY_UNIT_ADDR(ctlr, input)

#define ADC_CHANNEL_CFG_FROM_DT_NODE(node_id) \
IF_ENABLED(DT_NODE_EXISTS(node_id), \
Expand Down
17 changes: 17 additions & 0 deletions scripts/dts/gen_defines.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python3

Check warning on line 1 in scripts/dts/gen_defines.py

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

License may not be allowed

scripts/dts/gen_defines.py:1 License file for 'BSD-3-Clause' not found in /LICENSES. Please check https://docs.zephyrproject.org/latest/contribute/guidelines.html#components-using-other-licenses.

# Copyright (c) 2019 - 2020 Nordic Semiconductor ASA
# Copyright (c) 2019 Linaro Limited
Expand Down Expand Up @@ -484,6 +484,23 @@

out_dt_define(f"{node.z_path_id}_CHILD_NUM_STATUS_OKAY", ok_nodes_num)

child_unit_addrs = {}
for child in node.children.values():
# Provide a way to query child nodes
if (addr := child.unit_addr) is not None:
child_unit_addrs.setdefault(addr, []).append(child)

for addr, children in child_unit_addrs.items():
if len(children) != 1:
# Duplicate unit addresses for different children, skip
continue

# Decimal and hexadecimal variants
out_dt_define(f"{node.z_path_id}_CHILD_UNIT_ADDR_{addr}", f"DT_{children[0].z_path_id}")
out_dt_define(
f"{node.z_path_id}_CHILD_UNIT_ADDR_{hex(addr)}", f"DT_{children[0].z_path_id}"
)

out_dt_define(f"{node.z_path_id}_FOREACH_CHILD(fn)",
" ".join(f"fn(DT_{child.z_path_id})" for child in
node.children.values()))
Expand Down
22 changes: 19 additions & 3 deletions tests/lib/devicetree/api/app.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@

test_pinctrl: pin-controller {
compatible = "vnd,pinctrl";

test_pincfg_a: pincfg-a {};

test_pincfg_b: pincfg-b {};

test_pincfg_c: pincfg-c {};

test_pincfg_d: pincfg-d {};
};

Expand Down Expand Up @@ -252,20 +256,24 @@
test_i2c_mux: i2c-mux@12 {
compatible = "vnd,i2c-mux";
reg = <0x12>;

i2c-mux-ctlr-1 {
compatible = "vnd,i2c-mux-controller";
#address-cells = <1>;
#size-cells = <0>;

test_muxed_i2c_dev_1: muxed-i2c-dev@10 {
compatible = "vnd,i2c-device";
status = "disabled";
reg = <0x10>;
};
};

i2c-mux-ctlr-2 {
compatible = "vnd,i2c-mux-controller";
#address-cells = <1>;
#size-cells = <0>;

test_muxed_i2c_dev_2: muxed-i2c-dev@10 {
compatible = "vnd,i2c-device";
status = "disabled";
Expand Down Expand Up @@ -650,16 +658,23 @@
/* there should only be one of these */
test_children: test-children {
compatible = "vnd,child-bindings";
#address-cells = <1>;
#size-cells = <0>;

test_child_a: child-a {
test_child_a: child@a {
reg = <0xa>;
val = <0>;
status = "okay";
};
test_child_b: child-b {

test_child_b: child@b {
reg = <0xb>;
val = <1>;
status = "okay";
};
test_child_c: child-c {

test_child_c: child@c {
reg = <0xc>;
val = <2>;
status = "disabled";
};
Expand Down Expand Up @@ -852,6 +867,7 @@
flash@20000000 {
compatible = "soc-nv-flash";
reg = <0x20000000 0x100>;

partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
Expand Down
20 changes: 20 additions & 0 deletions tests/lib/devicetree/api/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2514,6 +2514,26 @@ ZTEST(devicetree_api, test_children)
zassert_equal(DT_PROP(DT_INST_CHILD(0, child_a), val), 0, "");
zassert_equal(DT_PROP(DT_INST_CHILD(0, child_b), val), 1, "");
zassert_equal(DT_PROP(DT_INST_CHILD(0, child_c), val), 2, "");

zassert_equal(DT_PROP(DT_CHILD_BY_UNIT_ADDR(DT_NODELABEL(test_children), 0xa),
val), 0, "");
zassert_equal(DT_PROP(DT_CHILD_BY_UNIT_ADDR(DT_NODELABEL(test_children), 10),
val), 0, "");
zassert_equal(DT_PROP(DT_CHILD_BY_UNIT_ADDR(DT_NODELABEL(test_children), 0xb),
val), 1, "");
zassert_equal(DT_PROP(DT_CHILD_BY_UNIT_ADDR(DT_NODELABEL(test_children), 11),
val), 1, "");
zassert_equal(DT_PROP(DT_CHILD_BY_UNIT_ADDR(DT_NODELABEL(test_children), 0xc),
val), 2, "");
zassert_equal(DT_PROP(DT_CHILD_BY_UNIT_ADDR(DT_NODELABEL(test_children), 12),
val), 2, "");

zassert_equal(DT_PROP(DT_INST_CHILD_BY_UNIT_ADDR(0, 0xa), val), 0, "");
zassert_equal(DT_PROP(DT_INST_CHILD_BY_UNIT_ADDR(0, 10), val), 0, "");
zassert_equal(DT_PROP(DT_INST_CHILD_BY_UNIT_ADDR(0, 0xb), val), 1, "");
zassert_equal(DT_PROP(DT_INST_CHILD_BY_UNIT_ADDR(0, 11), val), 1, "");
zassert_equal(DT_PROP(DT_INST_CHILD_BY_UNIT_ADDR(0, 0xc), val), 2, "");
zassert_equal(DT_PROP(DT_INST_CHILD_BY_UNIT_ADDR(0, 12), val), 2, "");
}

#undef DT_DRV_COMPAT
Expand Down
Loading