Skip to content

Commit 7e92b70

Browse files
decsnyhenrikbrixandersen
authored andcommitted
include: devicetree: Add more PHA macros
Add more macros for interacting with controller/data type of relationships (phandle arrays / cells) Add macros for arbitrarily iterating cells of phandle specifiers Add tests for the new macros Signed-off-by: Declan Snyder <[email protected]>
1 parent 8d61b36 commit 7e92b70

File tree

4 files changed

+223
-7
lines changed

4 files changed

+223
-7
lines changed

include/zephyr/devicetree.h

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3817,6 +3817,134 @@
38173817
#define DT_PHA_HAS_CELL(node_id, pha, cell) \
38183818
DT_PHA_HAS_CELL_AT_IDX(node_id, pha, 0, cell)
38193819

3820+
/**
3821+
* @brief Iterate over all cells in a phandle array element by index
3822+
*
3823+
* This macro calls @p fn(cell_value) for each cell value in the
3824+
* phandle array element at index @p idx.
3825+
*
3826+
* In general, this macro expands to:
3827+
*
3828+
* fn(node_id, pha, idx, cell[0]) fn(node_id, pha, idx, cell[1]) [...]
3829+
* fn(node_id, pha, idx, cell[n-1])
3830+
*
3831+
* where `n` is the number of cells in @p pha, as it would be
3832+
* returned by `DT_PHA_NUM_CELLS_BY_IDX(node_id, pha, idx)`, and cell[x] is the NAME of the cell
3833+
* in the specifier.
3834+
*
3835+
* @param node_id node identifier
3836+
* @param pha lowercase-and-underscores property with type `phandle-array`
3837+
* @param idx index of the phandle array element
3838+
* @param fn macro to call for each cell value
3839+
*/
3840+
#define DT_FOREACH_PHA_CELL_BY_IDX(node_id, pha, idx, fn) \
3841+
DT_CAT6(node_id, _P_, pha, _IDX_, idx, _FOREACH_CELL)(fn)
3842+
3843+
/**
3844+
* @brief Iterate over all cells in a phandle array element by index with separator
3845+
*
3846+
* This is like DT_FOREACH_PHA_CELL_BY_IDX(), but @p sep is placed between
3847+
* each invocation of @p fn.
3848+
*
3849+
* @param node_id node identifier
3850+
* @param pha lowercase-and-underscores property with type `phandle-array`
3851+
* @param idx index of the phandle array element
3852+
* @param fn macro to call for each cell value
3853+
* @param sep separator (e.g. comma or semicolon)
3854+
*/
3855+
#define DT_FOREACH_PHA_CELL_BY_IDX_SEP(node_id, pha, idx, fn, sep) \
3856+
DT_CAT6(node_id, _P_, pha, _IDX_, idx, _FOREACH_CELL_SEP)(fn, sep)
3857+
3858+
/**
3859+
* @brief Get the number of cells in a phandle array element by index
3860+
*
3861+
* @param node_id node identifier
3862+
* @param pha lowercase-and-underscores property with type `phandle-array`
3863+
* @param idx index of the phandle array element
3864+
* @return number of cells in the element at index @p idx
3865+
*/
3866+
#define DT_PHA_NUM_CELLS_BY_IDX(node_id, pha, idx) \
3867+
DT_CAT6(node_id, _P_, pha, _IDX_, idx, _NUM_CELLS)
3868+
3869+
/**
3870+
* @brief Get the name of a phandle array element by index
3871+
*
3872+
* This returns the name in the *-names property of the node
3873+
* corresponding to the index @p idx of @p pha
3874+
*
3875+
* @param node_id node identifier
3876+
* @param pha lowercase-and-underscores property with type `phandle-array`
3877+
* @param idx index of the phandle array element
3878+
* @return name of the element at index @p idx
3879+
*/
3880+
#define DT_PHA_ELEM_NAME_BY_IDX(node_id, pha, idx) \
3881+
DT_CAT6(node_id, _P_, pha, _IDX_, idx, _NAME)
3882+
3883+
/**
3884+
* @brief Iterate over all cells in a phandle array element by name
3885+
*
3886+
* This macro calls @p fn(cell_value) for each cell value in the
3887+
* phandle array @p pha element with the given @p name in the *-names property.
3888+
*
3889+
* In general, this macro expands to:
3890+
*
3891+
* fn(node_id, pha, name, cell[0]) fn(node_id, pha, idx, cell[1]) [...]
3892+
* fn(node_id, pha, idx, cell[n-1])
3893+
*
3894+
* where `n` is the number of cells in @p pha, as it would be
3895+
* returned by `DT_PHA_NUM_CELLS_BY_NAME(node_id, pha, name)`, and cell[x] is the NAME of the cell
3896+
* in the specifier.
3897+
*
3898+
*
3899+
* @param node_id node identifier
3900+
* @param pha lowercase-and-underscores property with type `phandle-array`
3901+
* @param name lowercase-and-underscores name of the phandle array element
3902+
* @param fn macro to call for each cell value
3903+
*/
3904+
#define DT_FOREACH_PHA_CELL_BY_NAME(node_id, pha, name, fn) \
3905+
DT_CAT6(node_id, _P_, pha, _NAME_, name, _FOREACH_CELL)(fn)
3906+
3907+
/**
3908+
* @brief Iterate over all cells in a phandle array element by name with separator
3909+
*
3910+
* This is like DT_FOREACH_PHA_CELL_BY_NAME(), but @p sep is placed between
3911+
* each invocation of @p fn.
3912+
*
3913+
* @param node_id node identifier
3914+
* @param pha lowercase-and-underscores property with type `phandle-array`
3915+
* @param name lowercase-and-underscores name of the phandle array element
3916+
* @param fn macro to call for each cell value
3917+
* @param sep separator (e.g. comma or semicolon)
3918+
*/
3919+
#define DT_FOREACH_PHA_CELL_BY_NAME_SEP(node_id, pha, name, fn, sep) \
3920+
DT_CAT6(node_id, _P_, pha, _NAME_, name, _FOREACH_CELL_SEP)(fn, sep)
3921+
3922+
/**
3923+
* @brief Get the number of cells in a phandle array element by name
3924+
*
3925+
* @param node_id node identifier
3926+
* @param pha lowercase-and-underscores property with type `phandle-array`
3927+
* @param name lowercase-and-underscores name of the phandle array element
3928+
* @return number of cells in the element with the given @p name
3929+
*/
3930+
#define DT_PHA_NUM_CELLS_BY_NAME(node_id, pha, name) \
3931+
DT_CAT6(node_id, _P_, pha, _NAME_, name, _NUM_CELLS)
3932+
3933+
/**
3934+
* @brief Get the index of a phandle array element by name
3935+
*
3936+
* This returns the index of the @p pha which has the name @p name in the corresponding
3937+
* *-names property.
3938+
*
3939+
* @param node_id node identifier
3940+
* @param pha lowercase-and-underscores property with type `phandle-array`
3941+
* @param name lowercase-and-underscores name of the phandle array element
3942+
* @return index of the element with the given @p name
3943+
*/
3944+
#define DT_PHA_ELEM_IDX_BY_NAME(node_id, pha, name) \
3945+
DT_CAT6(node_id, _P_, pha, _NAME_, name, _IDX)
3946+
3947+
38203948
/**
38213949
* @}
38223950
*/

scripts/dts/gen_defines.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ def write_gpio_hogs(node: edtlib.Node) -> None:
569569
macro = f"{node.z_path_id}_GPIO_HOGS"
570570
macro2val = {}
571571
for i, entry in enumerate(node.gpio_hogs):
572-
macro2val.update(controller_and_data_macros(entry, i, macro))
572+
macro2val.update(controller_and_data_macros(entry, i, macro, ""))
573573

574574
if macro2val:
575575
out_comment("GPIO hog properties:")
@@ -835,12 +835,12 @@ def phandle_macros(prop: edtlib.Property, macro: str) -> dict:
835835
ret[f"{macro}_IDX_{i}_EXISTS"] = 0
836836
continue
837837

838-
ret.update(controller_and_data_macros(entry, i, macro))
838+
ret.update(controller_and_data_macros(entry, i, macro, prop.name))
839839

840840
return ret
841841

842842

843-
def controller_and_data_macros(entry: edtlib.ControllerAndData, i: int, macro: str):
843+
def controller_and_data_macros(entry: edtlib.ControllerAndData, i: int, macro: str, pname: str):
844844
# Helper procedure used by phandle_macros().
845845
#
846846
# Its purpose is to write the "controller" (i.e. label property of
@@ -849,6 +849,8 @@ def controller_and_data_macros(entry: edtlib.ControllerAndData, i: int, macro: s
849849

850850
ret = {}
851851
data = entry.data
852+
node = entry.node
853+
pname = edtlib.str_as_token(str2ident(pname))
852854

853855
# DT_N_<node-id>_P_<prop-id>_IDX_<i>_EXISTS
854856
ret[f"{macro}_IDX_{i}_EXISTS"] = 1
@@ -858,13 +860,40 @@ def controller_and_data_macros(entry: edtlib.ControllerAndData, i: int, macro: s
858860
for cell, val in data.items():
859861
ret[f"{macro}_IDX_{i}_VAL_{str2ident(cell)}"] = val
860862
ret[f"{macro}_IDX_{i}_VAL_{str2ident(cell)}_EXISTS"] = 1
863+
# DT_N_<node-id>_P_<prop-id>_IDX_<i>_EXISTS
864+
ret[f"{macro}_IDX_{i}_EXISTS"] = 1
865+
# DT_N_<node-id>_P_<prop-id>_IDX_<i>_FOREACH_CELL
866+
ret[f"{macro}_IDX_{i}_FOREACH_CELL(fn)"] = (
867+
' \\\n\t'.join(f'fn(DT_{node.z_path_id}, {pname}, {i}, {cell})'
868+
for cell in data))
869+
# DT_N_<node-id>_P_<prop-id>_IDX_<i>_FOREACH_CELL_SEP
870+
ret[f"{macro}_IDX_{i}_FOREACH_CELL_SEP(fn, sep)"] = (
871+
' DT_DEBRACKET_INTERNAL sep \\\n\t'.join(
872+
f'fn(DT_{node.z_path_id}, {pname}, {i}, {cell})'
873+
for cell in data))
874+
# DT_N_<node-id>_P_<prop-id>_IDX_<i>_NUM_CELLS
875+
ret[f"{macro}_IDX_{i}_NUM_CELLS"] = len(data)
861876

862877
if not entry.name:
863878
return ret
864879

865880
name = str2ident(entry.name)
866-
# DT_N_<node-id>_P_<prop-id>_IDX_<i>_EXISTS
867-
ret[f"{macro}_IDX_{i}_EXISTS"] = 1
881+
882+
# DT_N_<node-id>_P_<prop-id>_IDX_<i>_NAME
883+
ret[f"{macro}_IDX_{i}_NAME"] = edtlib.str_as_token(name)
884+
# DT_N_<node-id>_P_<prop-id>_NAME_<name>_IDX
885+
ret[f"{macro}_NAME_{name}_IDX"] = i
886+
# DT_N_<node-id>_P_<prop-id>_NAME_<name>_FOREACH_CELL
887+
ret[f"{macro}_NAME_{name}_FOREACH_CELL(fn)"] = (
888+
' \\\n\t'.join(f'fn(DT_{node.z_path_id}, {pname}, {name}, {cell})'
889+
for cell in data))
890+
# DT_N_<node-id>_P_<prop-id>_NAME_<name>_FOREACH_CELL_SEP
891+
ret[f"{macro}_NAME_{name}_FOREACH_CELL_SEP(fn, sep)"] = (
892+
' DT_DEBRACKET_INTERNAL sep \\\n\t'.join(
893+
f'fn(DT_{node.z_path_id}, {pname}, {name}, {cell})'
894+
for cell in data))
895+
# DT_N_<node-id>_P_<prop-id>_NAME_<name>_NUM_CELLS
896+
ret[f"{macro}_NAME_{name}_NUM_CELLS"] = len(data)
868897
# DT_N_<node-id>_P_<prop-id>_IDX_<i>_NAME
869898
ret[f"{macro}_IDX_{i}_NAME"] = quote_str(entry.name)
870899
# DT_N_<node-id>_P_<prop-id>_NAME_<NAME>_PH

scripts/dts/python-devicetree/src/devicetree/edtlib.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ class ControllerAndData:
855855
*-names property
856856
857857
basename:
858-
Basename for the controller when supporting named cells
858+
Basename for the controller when supporting named cells. AKA, the specifier space.
859859
"""
860860
node: 'Node'
861861
controller: 'Node'

tests/lib/devicetree/api/src/main.c

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#define TEST_NODELABEL DT_NODELABEL(test_nodelabel)
1919
#define TEST_INST DT_INST(0, vnd_gpio_device)
2020
#define TEST_ARRAYS DT_NODELABEL(test_arrays)
21-
#define TEST_PH DT_NODELABEL(test_phandles)
21+
#define TEST_PH DT_NODELABEL(test_phandles)
2222
#define TEST_INTC DT_NODELABEL(test_intc)
2323
#define TEST_IRQ DT_NODELABEL(test_irq)
2424
#define TEST_IRQ_EXT DT_NODELABEL(test_irq_extended)
@@ -1114,6 +1114,65 @@ ZTEST(devicetree_api, test_phandles)
11141114
zassert_true(DT_SAME_NODE(DT_PHANDLE_BY_NAME(TEST_PH, foos, a), TEST_GPIO_1), "");
11151115
zassert_true(DT_SAME_NODE(DT_PHANDLE_BY_NAME(TEST_PH, foos, b_c), TEST_GPIO_2), "");
11161116

1117+
/* DT_PHA_NUM_CELLS_BY_IDX */
1118+
zassert_equal(DT_PHA_NUM_CELLS_BY_IDX(TEST_PH, foos, 0), 1);
1119+
zassert_equal(DT_PHA_NUM_CELLS_BY_IDX(TEST_PH, pha_gpios, 2), 1);
1120+
zassert_equal(DT_PHA_NUM_CELLS_BY_IDX(TEST_PH, pha_gpios, 3), 2);
1121+
1122+
/* DT_PHA_NUM_CELLS_BY_NAME */
1123+
zassert_equal(DT_PHA_NUM_CELLS_BY_NAME(TEST_PH, foos, a), 1);
1124+
zassert_equal(DT_PHA_NUM_CELLS_BY_NAME(TEST_PH, pwms, green), 3);
1125+
zassert_equal(DT_PHA_NUM_CELLS_BY_NAME(TEST_PH, pwms, red), 3);
1126+
1127+
/* DT_PHA_ELEM_NAME_BY_IDX */
1128+
zassert_str_equal(DT_PHA_ELEM_NAME_BY_IDX(TEST_PH, foos, 0), "A");
1129+
zassert_str_equal(DT_PHA_ELEM_NAME_BY_IDX(TEST_PH, foos, 1), "b-c");
1130+
zassert_str_equal(DT_PHA_ELEM_NAME_BY_IDX(TEST_PH, pwms, 0), "red");
1131+
zassert_str_equal(DT_PHA_ELEM_NAME_BY_IDX(TEST_PH, pwms, 1), "green");
1132+
1133+
/* DT_PHA_ELEM_IDX_BY_NAME */
1134+
zassert_equal(DT_PHA_ELEM_IDX_BY_NAME(TEST_PH, foos, a), 0);
1135+
zassert_equal(DT_PHA_ELEM_IDX_BY_NAME(TEST_PH, foos, b_c), 1);
1136+
zassert_equal(DT_PHA_ELEM_IDX_BY_NAME(TEST_PH, pwms, red), 0);
1137+
zassert_equal(DT_PHA_ELEM_IDX_BY_NAME(TEST_PH, pwms, green), 1);
1138+
1139+
/* DT_FOREACH_PHA_CELL_BY_IDX */
1140+
int chksum;
1141+
1142+
#define ADD_TWO(node_id, pha, idx, x) (DT_PHA_BY_IDX(node_id, pha, idx, x) + 2) +
1143+
chksum = DT_FOREACH_PHA_CELL_BY_IDX(TEST_PH, pwms, 0, ADD_TWO) 0;
1144+
zassert_equal(chksum, 211 + 6);
1145+
chksum = DT_FOREACH_PHA_CELL_BY_IDX(TEST_PH, foos, 1, ADD_TWO) 0;
1146+
zassert_equal(chksum, 110 + 2);
1147+
1148+
/* DT_FOREACH_PHA_CELL_BY_IDX_SEP */
1149+
int cells_one[2] = {
1150+
DT_FOREACH_PHA_CELL_BY_IDX_SEP(TEST_PH, pha_gpios, 0, DT_PHA_BY_IDX, (,))
1151+
};
1152+
int cells_two[1] = {
1153+
DT_FOREACH_PHA_CELL_BY_IDX_SEP(TEST_PH, pha_gpios, 2, DT_PHA_BY_IDX, (,))
1154+
};
1155+
1156+
zassert_equal(cells_one[0], 50);
1157+
zassert_equal(cells_one[1], 60);
1158+
zassert_equal(cells_two[0], 70);
1159+
1160+
/* DT_FOREACH_PHA_CELL_BY_NAME */
1161+
#define ADD_THREE(node_id, pha, idx, x) (DT_PHA_BY_NAME(node_id, pha, idx, x) + 3) +
1162+
chksum = DT_FOREACH_PHA_CELL_BY_NAME(TEST_PH, pwms, red, ADD_THREE) 0;
1163+
zassert_equal(chksum, 211 + 9);
1164+
chksum = DT_FOREACH_PHA_CELL_BY_NAME(TEST_PH, pwms, green, ADD_THREE) 0;
1165+
zassert_equal(chksum, 106 + 9);
1166+
1167+
/* DT_FOREACH_PHA_CELL_BY_NAME_SEP */
1168+
int cells_pwms[3] = {
1169+
DT_FOREACH_PHA_CELL_BY_NAME_SEP(TEST_PH, pwms, green, DT_PHA_BY_NAME, (,))
1170+
};
1171+
1172+
zassert_equal(cells_pwms[0], 5);
1173+
zassert_equal(cells_pwms[1], 100);
1174+
zassert_equal(cells_pwms[2], 1);
1175+
11171176
/* array initializers */
11181177
zassert_equal(gps[0].pin, 10, "");
11191178
zassert_equal(gps[0].flags, 20, "");

0 commit comments

Comments
 (0)