power_domain: gpio: only run actions for children on domain
Only run the `PM_DEVICE_ACTION_TURN_ON` and `PM_DEVICE_ACTION_TURN_OFF` actions for child devices that have refered to the domain via the `power-domain` property. This prevents multiple actions being run for devices that refer to several power domains, e.g. ``` test_dev: test_dev { compatible = "test-device-pm"; status = "okay"; power-domain = <&test_reg_1>; alternate-domain = <&test_reg_chained>; }; ``` Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
This commit is contained in:
parent
3b7e7575a9
commit
addf405fe6
1 changed files with 25 additions and 4 deletions
|
@ -25,11 +25,30 @@ struct pd_gpio_data {
|
||||||
k_timeout_t next_boot;
|
k_timeout_t next_boot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pd_visitor_context {
|
||||||
|
const struct device *domain;
|
||||||
|
enum pm_device_action action;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pd_on_domain_visitor(const struct device *dev, void *context)
|
||||||
|
{
|
||||||
|
struct pd_visitor_context *visitor_context = context;
|
||||||
|
|
||||||
|
/* Only run action if the device is on the specified domain */
|
||||||
|
if (!dev->pm || (dev->pm->domain != visitor_context->domain)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)pm_device_action_run(dev, visitor_context->action);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int pd_gpio_pm_action(const struct device *dev,
|
static int pd_gpio_pm_action(const struct device *dev,
|
||||||
enum pm_device_action action)
|
enum pm_device_action action)
|
||||||
{
|
{
|
||||||
const struct pd_gpio_config *cfg = dev->config;
|
const struct pd_gpio_config *cfg = dev->config;
|
||||||
struct pd_gpio_data *data = dev->data;
|
struct pd_gpio_data *data = dev->data;
|
||||||
|
struct pd_visitor_context context = {.domain = dev};
|
||||||
int64_t next_boot_ticks;
|
int64_t next_boot_ticks;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
@ -48,12 +67,14 @@ static int pd_gpio_pm_action(const struct device *dev,
|
||||||
LOG_INF("%s is now ON", dev->name);
|
LOG_INF("%s is now ON", dev->name);
|
||||||
/* Wait for domain to come up */
|
/* Wait for domain to come up */
|
||||||
k_sleep(K_USEC(cfg->startup_delay_us));
|
k_sleep(K_USEC(cfg->startup_delay_us));
|
||||||
/* Notify supported devices they are now powered */
|
/* Notify devices on the domain they are now powered */
|
||||||
pm_device_children_action_run(dev, PM_DEVICE_ACTION_TURN_ON, NULL);
|
context.action = PM_DEVICE_ACTION_TURN_ON;
|
||||||
|
(void)device_supported_foreach(dev, pd_on_domain_visitor, &context);
|
||||||
break;
|
break;
|
||||||
case PM_DEVICE_ACTION_SUSPEND:
|
case PM_DEVICE_ACTION_SUSPEND:
|
||||||
/* Notify supported devices power is going down */
|
/* Notify devices on the domain that power is going down */
|
||||||
pm_device_children_action_run(dev, PM_DEVICE_ACTION_TURN_OFF, NULL);
|
context.action = PM_DEVICE_ACTION_TURN_OFF;
|
||||||
|
(void)device_supported_foreach(dev, pd_on_domain_visitor, &context);
|
||||||
/* Switch power off */
|
/* Switch power off */
|
||||||
gpio_pin_set_dt(&cfg->enable, 0);
|
gpio_pin_set_dt(&cfg->enable, 0);
|
||||||
LOG_INF("%s is now OFF", dev->name);
|
LOG_INF("%s is now OFF", dev->name);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue