Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

devicetree: supported devices API #37793

Closed
JordanYates opened this issue Aug 19, 2021 · 4 comments
Closed

devicetree: supported devices API #37793

JordanYates opened this issue Aug 19, 2021 · 4 comments
Assignees
Labels

Comments

@JordanYates
Copy link
Collaborator

Is your enhancement proposal related to a problem? Please describe.

Some classes of devices need to be able to iterate over a complete list of devices that they are supporting in order to perform actions automatically. The primary use-case I have in mind is for regulator-fixed devices. Consider a hardware design such as:

power

When neither flash or GPS are being used, the regulator should be switched off to reduce power consumption.
But when the regulator is turned on in order to use the flash, it should be possible to automatically put the GPS into its lowest power state. (Ublox GPS modems by default start up in active mode, drawing ~30mA).

As it is unreasonable to expect all code using a flash chip to know which other devices are on the same regulator, the desired functionality requires it be possible to start at the regulator device and iterate over all devices that it supports.

It is currently possible to iterate over devices in the opposite direction (all dependencies of a device), thanks to #32127.
It is not currently possible to iterate over all devices that a device supports.

A list of supported devices is exposed through the _SUPPORTS_ORDS devicetree property, but this enumerates devicetree ordinals, not device handles. It is not currently possible to obtain a const struct device * from an ordinal.

As a short example of what this would enable:

const struct device *dev = DEVICE_DT_GET(DT_INST(0, compat);

/* Automatically walks the dependency tree, turning on all power supplies found.
 * For each power supply found, walk the supported devices and call pm_device_state_set(PM_DEVICE_STATE_LOW_POWER);
 */
pm_device_power_request(dev);
pm_device_get(dev);

/* Do things with compat */
...

pm_device_put(dev);
/* Does the opposite of pm_device_power_request() */
pm_device_power_release(dev);

Describe the solution you'd like

The solution that makes the most sense to me is to perform the same operations for supported devices as for dependent devices. Generate an array of the right length in the first link-stage and replace it in a later link stage with handles generated by gen_handles.py. This array could then be iterated at runtime in the same manner as device_required_foreach.

An alternate solution is to make it possible to convert devicetree ordinals to deviec handles via an array of (ordinal, handle) pairs.

Additional context

I don't believe that the requirement to walk supporting devices is general enough to justify an array in the core device struct like the dependency array, but maybe it is.

zephyr/include/device.h

Lines 377 to 384 in 9b6122d

/** optional pointer to handles associated with the device.
*
* This encodes a sequence of sets of device handles that have
* some relationship to this node. The individual sets are
* extracted with dedicated API, such as
* device_required_handles_get().
*/
const device_handle_t *const handles;

@mbolivar-nordic
Copy link
Contributor

Thanks for the clear analysis and description.

I don't believe that the requirement to walk supporting devices is general enough to justify an array in the core device struct like the dependency array, but maybe it is.

I think @gmarull is better situated to comment on the implementation details, but I actually think it is justified, personally.

If you look in the test cases related to ordinals, I anticipated this use case being handled in exactly that way:

unsigned int children_combined_ords_expected[] = {
/*
* Combined ordinals for /test/test-children are from
* these nodes in this order:
*/
DT_DEP_ORD(TEST_CHILDREN), /* node */
DT_DEP_ORD(DT_PATH(test)), /* parent */
DT_DEP_ORD(DT_NODELABEL(test_child_a)), /* children */
DT_DEP_ORD(DT_NODELABEL(test_child_b)),
DT_DEP_ORD(DT_NODELABEL(test_child_c)),
ORD_LIST_SEP, /* separator */
DT_DEP_ORD(DT_PATH(test)), /* requires */
INJECTED_DEP_0, /* injected
* dependencies
*/
INJECTED_DEP_1,
ORD_LIST_SEP, /* separator */
DT_DEP_ORD(DT_NODELABEL(test_child_a)), /* supports */
DT_DEP_ORD(DT_NODELABEL(test_child_b)),
DT_DEP_ORD(DT_NODELABEL(test_child_c)),
ORD_LIST_END, /* terminator */
};

Nobody's gotten around to doing this sort of thing in device.h yet is all, or at least that's what I understand.

I could see turning off the extra ROM if you don't need it, depending on some PM Kconfigs perhaps.

@JordanYates
Copy link
Collaborator Author

but I actually think it is justified, personally.

It is certainly convenient, and simply extending the existing handles array makes the implementation a whole lot cleaner. The documentation around the handles array already specified it was for all nodes with relationships, not just dependent devices.

nashif pushed a commit that referenced this issue Aug 25, 2021
Adds an API to query and visit supported devices. Follows the example
set by the required devices API.

Implements #37793.

Signed-off-by: Jordan Yates <[email protected]>
@carlescufi carlescufi reopened this Oct 13, 2021
@ceolin ceolin self-assigned this Oct 21, 2021
@ceolin
Copy link
Member

ceolin commented Oct 28, 2021

#39581

carlescufi pushed a commit that referenced this issue Nov 23, 2021
Adds an API to query and visit supported devices. Follows the example
set by the required devices API.

Implements #37793.

Signed-off-by: Jordan Yates <[email protected]>
@JordanYates
Copy link
Collaborator Author

Implemented in #40418

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants