Skip to content

Commit acbb960

Browse files
authored
Merge pull request zephyrproject-rtos#29 from whisperai/nlapp/gen2/pull-in-power-domain-gpio-fixes
Nlapp/gen2/pull in power domain gpio fixes
2 parents 0c8cfdb + 291f7db commit acbb960

File tree

4 files changed

+51
-17
lines changed

4 files changed

+51
-17
lines changed

drivers/power_domain/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,13 @@ menuconfig POWER_DOMAIN
88

99
if POWER_DOMAIN
1010

11+
module = POWER_DOMAIN
12+
module-str = power_domain
13+
source "subsys/logging/Kconfig.template.log_config"
14+
1115
config POWER_DOMAIN_GPIO
1216
bool "GPIO controlled power domain"
1317
depends on GPIO
18+
depends on TIMEOUT_64BIT
1419

1520
endif

drivers/power_domain/power_domain_gpio.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
#define DT_DRV_COMPAT power_domain_gpio
99

10-
#include <kernel.h>
11-
#include <drivers/gpio.h>
12-
#include <pm/device.h>
13-
#include <pm/device_runtime.h>
10+
#include <zephyr/kernel.h>
11+
#include <zephyr/drivers/gpio.h>
12+
#include <zephyr/pm/device.h>
13+
#include <zephyr/pm/device_runtime.h>
1414

15-
#include <logging/log.h>
16-
LOG_MODULE_REGISTER(power_domain_gpio, LOG_LEVEL_INF);
15+
#include <zephyr/logging/log.h>
16+
LOG_MODULE_REGISTER(power_domain_gpio, CONFIG_POWER_DOMAIN_LOG_LEVEL);
1717

1818
struct pd_gpio_config {
1919
struct gpio_dt_spec enable;
@@ -22,28 +22,32 @@ struct pd_gpio_config {
2222
};
2323

2424
struct pd_gpio_data {
25-
k_timeout_t last_boot;
25+
k_timeout_t next_boot;
2626
};
2727

28-
const char *actions[] = {
29-
[PM_DEVICE_ACTION_RESUME] = "RESUME",
30-
[PM_DEVICE_ACTION_SUSPEND] = "SUSPEND",
31-
[PM_DEVICE_ACTION_TURN_ON] = "TURN ON",
32-
[PM_DEVICE_ACTION_TURN_OFF] = "TURN OFF"
33-
};
34-
35-
3628
static int pd_gpio_pm_action(const struct device *dev,
3729
enum pm_device_action action)
3830
{
3931
const struct pd_gpio_config *cfg = dev->config;
32+
struct pd_gpio_data *data = dev->data;
33+
int64_t next_boot_ticks;
4034
int rc = 0;
4135

36+
/* Validate that blocking API's can be used */
37+
if (!k_can_yield()) {
38+
LOG_ERR("Blocking actions cannot run in this context");
39+
return -ENOTSUP;
40+
}
41+
4242
switch (action) {
4343
case PM_DEVICE_ACTION_RESUME:
44+
/* Wait until we can boot again */
45+
k_sleep(data->next_boot);
4446
/* Switch power on */
4547
gpio_pin_set_dt(&cfg->enable, 1);
46-
LOG_DBG("%s is now ON", dev->name);
48+
LOG_INF("%s is now ON", dev->name);
49+
/* Wait for domain to come up */
50+
k_sleep(K_USEC(cfg->startup_delay_us));
4751
/* Notify supported devices they are now powered */
4852
pm_device_children_action_run(dev, PM_DEVICE_ACTION_TURN_ON, NULL);
4953
break;
@@ -52,7 +56,10 @@ static int pd_gpio_pm_action(const struct device *dev,
5256
pm_device_children_action_run(dev, PM_DEVICE_ACTION_TURN_OFF, NULL);
5357
/* Switch power off */
5458
gpio_pin_set_dt(&cfg->enable, 0);
55-
LOG_DBG("%s is now OFF and powered", dev->name);
59+
LOG_INF("%s is now OFF", dev->name);
60+
/* Store next time we can boot */
61+
next_boot_ticks = k_uptime_ticks() + k_us_to_ticks_ceil32(cfg->off_on_delay_us);
62+
data->next_boot = K_TIMEOUT_ABS_TICKS(next_boot_ticks);
5663
break;
5764
case PM_DEVICE_ACTION_TURN_ON:
5865
/* Actively control the enable pin now that the device is powered */
@@ -74,12 +81,15 @@ static int pd_gpio_pm_action(const struct device *dev,
7481
static int pd_gpio_init(const struct device *dev)
7582
{
7683
const struct pd_gpio_config *cfg = dev->config;
84+
struct pd_gpio_data *data = dev->data;
7785
int rc;
7886

7987
if (!device_is_ready(cfg->enable.port)) {
8088
LOG_ERR("GPIO port %s is not ready", cfg->enable.port->name);
8189
return -ENODEV;
8290
}
91+
/* We can't know how long the domain has been off for before boot */
92+
data->next_boot = K_TIMEOUT_ABS_US(cfg->off_on_delay_us);
8393

8494
if (pm_device_on_power_domain(dev)) {
8595
/* Device is unpowered */

include/zephyr/kernel.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,19 @@ __syscall int32_t k_usleep(int32_t us);
464464
*/
465465
__syscall void k_busy_wait(uint32_t usec_to_wait);
466466

467+
/**
468+
* @brief Check whether it is possible to yield in the current context.
469+
*
470+
* This routine checks whether the kernel is in a state where it is possible to
471+
* yield or call blocking API's. It should be used by code that needs to yield
472+
* to perform correctly, but can feasibly be called from contexts where that
473+
* is not possible. For example in the PRE_KERNEL initialization step, or when
474+
* being run from the idle thread.
475+
*
476+
* @return True if it is possible to yield in the current context, false otherwise.
477+
*/
478+
bool k_can_yield(void);
479+
467480
/**
468481
* @brief Yield the current thread.
469482
*

kernel/sched.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,12 @@ static inline void z_vrfy_k_thread_deadline_set(k_tid_t tid, int deadline)
13251325
#endif
13261326
#endif
13271327

1328+
bool k_can_yield(void)
1329+
{
1330+
return !(k_is_pre_kernel() || k_is_in_isr() ||
1331+
z_is_idle_thread_object(_current));
1332+
}
1333+
13281334
void z_impl_k_yield(void)
13291335
{
13301336
__ASSERT(!arch_is_in_isr(), "");

0 commit comments

Comments
 (0)