Skip to content

Introduce pm_device_runtime_get/put_all() #93146

@bjarki-andreasen

Description

@bjarki-andreasen

Problem Description

PM_DEVICE_RUNTIME provides an excellent, flexible framework for power management of devices and their dependencies, at the cost of having applications and subsystems actually do power management explicitly. Some users may find it tedious to manually get/put every device before/after they use them from their applications individually, which is required for PM_DEVICE_RUNTIME to work reliably.

Proposed Change (Summary)

Introduce a set of "global" PM_DEVICE_RUNTIME get and put calls, which an application can call before using any device, and after its done using any devices, to allow the system to go to sleep. This will allow the zephyr kernel and it the zephyr subsystems to individually manage devices efficiently using PM_DEVICE_RUNTIME, while providing applications a simple way to do power management on top, at the cost of increased power consumption.

So, an application could go from this

int main(void)
{
        pm_device_runtime_get(i2c_dev);
        i2c_transfer(i2c_dev, msgs, num_msgs, addr);
        k_msleep(10);
        i2c_transfer(i2c_dev, msgs, num_msgs, addr);
        pm_device_runtime_put(i2c_dev);

        pm_device_runtime_get(spi_dev);
        spi_tranceive(spi_dev, config, tx_bufs, rx_bufs);
        k_msleep(10);
        spi_tranceive(spi_dev, config, tx_bufs, rx_bufs);
        pm_device_runtime_put(spi_dev);

        return 0;
}

to

int main(void)
{
        pm_device_runtime_get_all();

        i2c_transfer(i2c_dev, msgs, num_msgs, addr);
        k_msleep(10);
        i2c_transfer(i2c_dev, msgs, num_msgs, addr);

        spi_tranceive(spi_dev, config, tx_bufs, rx_bufs);
        k_msleep(10);
        spi_tranceive(spi_dev, config, tx_bufs, rx_bufs);

        pm_device_runtime_put_all();
        return 0;
}

Since everything is reference counted, even pm_device_runtime_get_all() and pm_device_runtime_put_all() can be called from any part of the application, providing something akin to a reference counted "system resume" / "system suspend".

Proposed Change (Detailed)

The additions is simple, introduce the two new APIs which simply iterate over every device in the system and get/put them.

__syscall int pm_device_runtime_get_all(void);

static inline int z_impl_pm_device_runtime_get_all(void)
{
        /* for every device, call pm_device_runtime_get() */
} 

__syscall int pm_device_runtime_put_all(void);

static inline int z_impl_pm_device_runtime_put_all(void)
{
        /* for every device, call pm_device_runtime_put(dev) */
} 

It is a safe addition on top of PM_DEVICE_RUNTIME which adds no additional cost if not used.

Dependencies

It depends on PM_DEVICE_RUNTIME.

Concerns and Unresolved Questions

This addition would remove the need for "inline" get/put calls within device drivers if users are ok with calling the one function before they start interacting with devices directly. It may be less power efficient than "inline" get/put calls where these can be used consistently, that is the potential cost of using these new APIs. It will be up to the user and their specific applications to decide if the simple get/put all calls are sufficient, or if finer power management is required, at which point the user will need to use pm_device_runtime_get/put.

Alternatives Considered

No response

Metadata

Metadata

Assignees

Labels

RFCRequest For Comments: want input from the communityarea: Power Management

Type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions