Skip to content

Conversation

@bjarki-andreasen
Copy link
Contributor

@bjarki-andreasen bjarki-andreasen commented May 21, 2025

This PR aims to document the status quo of device power management to provide a foundation for current driver development, and future refactoring discussions, since we need to agree on the current state before being able to discuss the future state :)

The PR also adds the missing counterpart to pm_device_driver_init().

Copy link
Contributor

@JordanYates JordanYates left a comment

Choose a reason for hiding this comment

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

What is the purpose of this function? It seems odd that it is running functions when CONFIG_PM_DEVICE=n but doesn't do anything when CONFIG_PM_DEVICE=y?

@bjarki-andreasen
Copy link
Contributor Author

bjarki-andreasen commented May 21, 2025

What is the purpose of this function? It seems odd that it is running functions when CONFIG_PM_DEVICE=n but doesn't do anything when CONFIG_PM_DEVICE=y?

Check out subsys/pm/device.c for now it simply ensures the device is not in use (suspended or off) to prevent deinit of a device which is in use. Even if it did nothing if CONFIG_PM_DEVICE=n, that would still be fine IMO, its there to allow device_deinit() to undo what device_init() did through pm_device_driver_init()

Copy link
Contributor

@JordanYates JordanYates left a comment

Choose a reason for hiding this comment

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

For now, this is a simple check ensuring the device is not in use

What is stopping a final implementation from being implemented now? The function should have defined semantics, and they should be implemented properly when the function is introduced, not modified at some point in "the future".

@bjarki-andreasen
Copy link
Contributor Author

bjarki-andreasen commented May 22, 2025

For now, this is a simple check ensuring the device is not in use

What is stopping a final implementation from being implemented now? The function should have defined semantics, and they should be implemented properly when the function is introduced, not modified at some point in "the future".

This is all we need for now, I don't think there is a "final" implementation, its just a hook for doing whatever is required of PM at a given time :)

return rc;
}

rc = action_cb(dev, PM_DEVICE_ACTION_TURN_OFF);
Copy link
Contributor

@JordanYates JordanYates May 22, 2025

Choose a reason for hiding this comment

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

This doesn't seem right, the device is not literally being turned off, just the software construct destroyed.
This would lead to GPIO's being put into incorrect states if used generically, which the PM API is.

Overloading the meaning of PM_DEVICE_ACTION_TURN_OFF is a bad idea IMO.

Copy link
Contributor Author

@bjarki-andreasen bjarki-andreasen May 22, 2025

Choose a reason for hiding this comment

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

I'm okay with removing the call to TURN_OFF, given that all resources like GPIOs are released as part of device_deinit(), I think you are right that it makes little sense to act as if the driver is being turned off before being deinitialized.

Copy link
Member

Choose a reason for hiding this comment

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

Agree about it

@bjarki-andreasen bjarki-andreasen force-pushed the pm-device-driver-deinit branch from 4ea0b00 to 0f5a01c Compare May 22, 2025 12:20
@bjarki-andreasen bjarki-andreasen force-pushed the pm-device-driver-deinit branch from 0f5a01c to 4a6a1d6 Compare May 25, 2025 18:55
ceolin
ceolin previously approved these changes May 26, 2025
@bjarki-andreasen
Copy link
Contributor Author

@JordanYates could you revisit this one?

Copy link
Contributor

@JordanYates JordanYates left a comment

Choose a reason for hiding this comment

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

It's still not clear to me how this helps to reliably implement the requirements of the device_deinit API.

* When a device is de-initialized, it will release any resources it has
* acquired (e.g. pins, memory, clocks, DMA channels, etc.) and its status will
* be left as in its reset state.
*
* @warning It is the responsibility of the caller to ensure that the device is
* ready to be de-initialized.

It's on the caller to determine whether the device can be de-initialized, not the implementation.

Why is STATE_SUSPENDED any more likely to be the "reset state" of a device than STATE_ACTIVE? In many cases the suspend state is explicitly not the reset state of a device.

@bjarki-andreasen
Copy link
Contributor Author

bjarki-andreasen commented May 29, 2025

It's still not clear to me how this helps to reliably implement the requirements of the device_deinit API.

* When a device is de-initialized, it will release any resources it has
* acquired (e.g. pins, memory, clocks, DMA channels, etc.) and its status will
* be left as in its reset state.
*
* @warning It is the responsibility of the caller to ensure that the device is
* ready to be de-initialized.

It's on the caller to determine whether the device can be de-initialized, not the implementation.

This to my knowledge was intended to clearly indicate that there is no reference counting or other tracking of who is using the device built in to the device model (which there was with an early version of device_deinit()), not that no checks are allowed to make sure it makes sense. Otherwise surely

zephyr/kernel/device.c

Lines 150 to 152 in 600cae6

if (!dev->state->initialized) {
return -EPERM;
}
would not exist :) The function returns a value, it can fail, we are allowed to do additional sanity checking.

Why is STATE_SUSPENDED any more likely to be the "reset state" of a device than STATE_ACTIVE? In many cases the suspend state is explicitly not the reset state of a device.

If CONFIG_PM_DEVICE=n, state is not checked, instead it just calls the suspend action. If CONFIG_PM_DEVICE=y, then device has to be suspended, thus STATE_SUSPENDED or STATE_OFF are explicitly states from which the "reset state" can be safely entered. The only difference between STATE_SUSPENDED and STATE_OFF would be whether the hardware block lost power, and thus was implicitly reset.

@JordanYates
Copy link
Contributor

As a concrete request, please document what the function is actually supposed to be doing beyond just @brief Deinit a device driver. It is easier to check that an intended behavior makes sense and that an implementation matches the intended behavior than to try and reason about how a particular implementation is supposed to fit into the larger device_deinit API based only on code.

@kartben kartben added this to the v4.3.0 milestone Jul 4, 2025
* :kconfig:option:`CONFIG_PM_DEVICE_RUNTIME_DEDICATED_WQ_PRIO`
* :kconfig:option:`CONFIG_PM_DEVICE_RUNTIME_DEDICATED_WQ_INIT_PRIO`
* :kconfig:option:`CONFIG_PM_DEVICE_RUNTIME_ASYNC`
* :c:func:`pm_device_driver_deinit`
Copy link
Member

@aescolar aescolar Jul 19, 2025

Choose a reason for hiding this comment

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

should this modify the 4.3 release notes? or is it meant as a backport?
(Feel free to disregard this review if all it needs is a backport label)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its not meant to be backported :) Release notes will be updated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated :)

@bjarki-andreasen bjarki-andreasen force-pushed the pm-device-driver-deinit branch from 5e0d6a2 to cc8e50b Compare July 21, 2025 08:14
@bjarki-andreasen bjarki-andreasen dismissed stale reviews from nashif and ceolin via 2814832 July 21, 2025 08:14
@bjarki-andreasen bjarki-andreasen force-pushed the pm-device-driver-deinit branch from cc8e50b to 2814832 Compare July 21, 2025 08:14
@bjarki-andreasen
Copy link
Contributor Author

Rebased and moved mention of introduction of pm_device_driver_deinit from release notes 4.2 to 4.3

@aescolar aescolar dismissed their stale review July 21, 2025 12:32

Addressed

@bjarki-andreasen
Copy link
Contributor Author

ping @JordanYates @decsny

decsny
decsny previously approved these changes Jul 23, 2025
ceolin
ceolin previously approved these changes Jul 26, 2025
Rewrite the docstring for pm_device_driver_init() to align with
documentation, especially covering the case where CONFIG_PM_DEVICE=n

Signed-off-by: Bjarki Arge Andreasen <[email protected]>
Introduce pm_device_driver_deinit() which is required to fully
support device_deinit(). This function shall be called by drivers
when device_deinit() is called.

If PM_DEVICE is enabled, it will
simply check whether the device is either SUSPENDED or OFF, this
will prevent device_deinit() on a device which is currently in
use, and ensure the device is in the correct state if device_init()
is called later.

If PM_DEVICE is not enabled, it will invoke the SUSPEND action which
mirrors the pm_device_driver_init() behavior. Note that TURN_OFF
action is not called since the device is deinitialized after this
call.

Signed-off-by: Bjarki Arge Andreasen <[email protected]>
Extend test suite to cover pm_device_driver_deinit() resulting
from call to device_deinit().

Signed-off-by: Bjarki Arge Andreasen <[email protected]>
- Specify "Device" Power Management Support in sections covering
  CONFIG_PM_DEVICE=y or n
- Extend the enum pm_device_state docstrings to define and detail
  expectations of devices in each enum pm_device_state state.
- Extend pm device driver code example with more concise comments
  and include pm_device_driver_init, pm_device_driver_deinit, and
  DEVICE_DT_INST_DEINIT_DEFINE() (device deinit feature)
- Describe the device driver PM states used if PM_DEVICE is not
  enabled.
- Note which states a device driver is initialized from and can
  be deinitialized in and why.

Signed-off-by: Bjarki Arge Andreasen <[email protected]>
Mention introduction of pm_device_driver_deinit() in the 4.3 release
notes.

Signed-off-by: Bjarki Arge Andreasen <[email protected]>
@bjarki-andreasen bjarki-andreasen dismissed stale reviews from ceolin and decsny via 36158b4 July 28, 2025 18:29
@bjarki-andreasen bjarki-andreasen force-pushed the pm-device-driver-deinit branch from 2814832 to 36158b4 Compare July 28, 2025 18:29
@bjarki-andreasen
Copy link
Contributor Author

Rebased again for release notes conflict

@sonarqubecloud
Copy link

@carlescufi carlescufi moved this from Todo to In Progress in Architecture Review Jul 28, 2025
@bjarki-andreasen
Copy link
Contributor Author

Pretty much everyone has approved this at some point, but I keep to have to rebase due to merge conflicts in release notes, please help :D

ping @ceolin @JordanYates @fabiobaltieri

Copy link
Contributor

@mathieuchopstm mathieuchopstm left a comment

Choose a reason for hiding this comment

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

Let's merge this before the next conflict 🙂

@cfriedt cfriedt merged commit f27168f into zephyrproject-rtos:main Jul 30, 2025
26 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in Architecture Review Jul 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: Power Management Release Notes To be mentioned in the release notes

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.