Skip to content
Closed
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
2 changes: 2 additions & 0 deletions doc/guides/dts/macros.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ node-macro =/ %s"DT_N" path-id %s"_IRQ_NAME_" dt-name
node-macro =/ %s"DT_N" path-id %s"_COMPAT_MATCHES_" dt-name
; The node identifier for the node's parent in the devicetree.
node-macro =/ %s"DT_N" path-id %s"_PARENT"
; The node identifier for the node's status
node-macro =/ %s"DT_N" path-id %s"_STATUS_" status

; --------------------------------------------------------------------
; property-macro: a macro related to a node property
Expand Down
34 changes: 33 additions & 1 deletion include/devicetree.h
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,38 @@
* @{
*/

/** @internal helper for DT_NODE_HAS_STATUS so we can additional
* macro expansion
*/
#define DT_NODE_HAS_STATUS_(node_id, status) \
IS_ENABLED(DT_CAT(node_id, _STATUS_##status))

/**
* @brief Does a devicetree node match a status?
*
* Example devicetree fragment:
*
* n: node {
* compatible = "generic-device";
* status = "okay";
* }
*
* Example usages which evaluate to 1:
*
* DT_NODE_HAS_STATUS(DT_NODELABEL(n), okay)
*
* Example usages which evaluate to 0:
*
* DT_NODE_HAS_STATUS(DT_NODELABEL(n), disabled)
*
* @param node_id node identifier
* @param status status value to check for
* @return 1 if the node's status property matches status,
* 0 otherwise.
*/
#define DT_NODE_HAS_STATUS(node_id, status) \
DT_NODE_HAS_STATUS_(node_id, status)

/**
* @brief Does a node identifier refer to a usable node?
*
Expand All @@ -898,7 +930,7 @@
* @return 1 if the node identifier refers to a usable node,
* 0 otherwise.
*/
#define DT_HAS_NODE_STATUS_OKAY(node_id) IS_ENABLED(DT_CAT(node_id, _EXISTS))
#define DT_HAS_NODE_STATUS_OKAY(node_id) DT_NODE_HAS_STATUS(node_id, okay)

/**
* @brief Does the devicetree have any usable nodes with a compatible?
Expand Down
45 changes: 37 additions & 8 deletions scripts/dts/edtlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ class Node:
A list with the nodes that the node directly depends on

enabled:
True unless the node has 'status = "disabled"'
True if 'status = "okay"', 'status = "ok"', or no status property.

read_only:
True if the node has a 'read-only' property, and False otherwise
Expand Down Expand Up @@ -914,7 +914,8 @@ def depends_on(self):
def enabled(self):
"See the class docstring"
return "status" not in self._node.props or \
self._node.props["status"].to_string() != "disabled"
self._node.props["status"].to_string() == "okay" or \
self._node.props["status"].to_string() == "ok"

@property
def read_only(self):
Expand Down Expand Up @@ -1087,15 +1088,43 @@ def _init_props(self):

self.props = OrderedDict()

if not self._binding:
return
node = self._node
if self._binding:
binding_props = self._binding.get("properties")
else:
binding_props = None

# Initialize self.props
if "properties" in self._binding:
for name, options in self._binding["properties"].items():
if binding_props:
for name, options in binding_props.items():
self._init_prop(name, options)

self._check_undeclared_props()
self._check_undeclared_props()
else:
common_prop_types = {
"compatible" : "string-array",
"status" : "string",
"reg" : "array",
"reg-names": "string-array",
"label" : "string",
"interrupt" : "array",
"interrupts-extended": "compound",
"interrupt-names": "string-array",
"interrupt-controller": "boolean",
}

for name in node.props:
if name in common_prop_types:
prop_type = common_prop_types[name]
val = self._prop_val(name, prop_type, False, None)
prop = Property()
prop.node = self
prop.name = name
prop.description = None
prop.val = val
prop.type = prop_type
# We don't set enum_index for "compatible"
prop.enum_index = None
self.props[name] = prop

def _init_prop(self, name, options):
# _init_props() helper for initializing a single property
Expand Down
19 changes: 16 additions & 3 deletions scripts/dts/gen_defines.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ def main():
if not node.enabled:
out_comment("No node macros: node is disabled")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if we're moving to #25002, I think this should be removed too, right? We had discussed being able to read any property we have semantics for (at least 'reg' and 'interrupts') regardless of status.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think things like compat2enabled in the EDT object may need changes, since we're changing the semantics of "enabled" in C to be status == "okay" instead of status != "disabled" and adding macros like DT_HAS_COMPAT_STATUS_OKAY in #25002. So it seems like we should be doing compat2statusokay or something instead.

In general I'm having trouble keeping all the pull requests together and I don't see enough Python changes to accompany all the C changes. What am I missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reworked how enabled was defined. If we want to leave that alone we can create a new 'available' which would be similar to the linux concept https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/of/base.c#n581

continue
if not node.matching_compat:
out_comment("No node macros: node has no matching binding")
continue

write_idents_and_existence(node)
write_bus(node)
Expand Down Expand Up @@ -244,6 +241,7 @@ def write_special_props(node):
write_regs(node)
write_interrupts(node)
write_compatibles(node)
write_status(node)


def write_regs(node):
Expand Down Expand Up @@ -359,6 +357,21 @@ def write_compatibles(node):
f"{node.z_path_id}_COMPAT_MATCHES_{str2ident(compat)}", 1)


def write_status(node):
# Writes a macro that we can utilize to test the "status" of a node
# We normalize status = "ok" to "okay", and if there is no "status"
# property we treat that as "okay"

if "status" in node.props:
status = node.props["status"].val
if status == "ok":
status = "okay"
else:
status = "okay"

out_dt_define(f"{node.z_path_id}_STATUS_{status}", 1)


def write_vanilla_props(node):
# Writes macros for any and all properties defined in the
# "properties" section of the binding for the node.
Expand Down
7 changes: 7 additions & 0 deletions tests/lib/devicetree/app.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@
status = "disabled";
};

test_no_status: intc_no_status@0 {
compatible = "vnd,intc";
reg = <0x0 0x1000>;
interrupt-controller;
#interrupt-cells = <2>;
};

test_nodelabel: TEST_NODELABEL_ALLCAPS: test_gpio_1: gpio@deadbeef {
compatible = "vnd,gpio";
gpio-controller;
Expand Down
22 changes: 22 additions & 0 deletions tests/lib/devicetree/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,27 @@ static void test_has_compat(void)
zassert_equal(compats, 0x3, "as bit array");
}

static void test_has_status(void)
{
zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(test_gpio_1), okay),
1, "vnd,gpio okay");
zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(test_gpio_1), disabled),
0, "vnd,gpio not disabled");

zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(test_no_status), okay),
1, "vnd,gpio okay");
zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(test_no_status), disabled),
0, "vnd,gpio not disabled");

/* Disabled for now until we generate something for non-"enabled" nodes */
#if 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving a comment here since we've merged ifdeffed out tests before, to make sure it doesn't happen this time

zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(disabled_gpio), disabled),
1, "vnd,disabled-compat disabled");
zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(disabled_gpio), okay),
0, "vnd,disabled-compat not okay");
#endif
}

#define TEST_I2C_DEV DT_PATH(test, i2c_11112222, test_i2c_dev_10)
#define TEST_I2C_BUS DT_BUS(TEST_I2C_DEV)

Expand Down Expand Up @@ -1381,6 +1402,7 @@ void test_main(void)
ztest_unit_test(test_inst_checks),
ztest_unit_test(test_has_nodelabel),
ztest_unit_test(test_has_compat),
ztest_unit_test(test_has_status),
ztest_unit_test(test_bus),
ztest_unit_test(test_reg),
ztest_unit_test(test_irq),
Expand Down