From e1639b5345d42d3107b949eb9bc01f782454feed Mon Sep 17 00:00:00 2001 From: Ramakrishna Pallala Date: Thu, 14 Feb 2019 09:35:42 +0530 Subject: [PATCH] device: Extend device_set_power_state API to support async requests The existing device_set_power_state() API works only in synchronous mode and this is not desirable for devices(ex: Gyro) which take longer time (few 100 mSec) to suspend/resume. To support async mode, a new callback argument is added to the API. The device drivers can asynchronously suspend/resume and call the callback function upon completion of the async request. This commit adds the missing callback parameter to all the drivers to make it compliant with the new API. Signed-off-by: Ramakrishna Pallala --- doc/reference/power_management/index.rst | 2 +- drivers/counter/counter_qmsi_aonpt.c | 15 +++++++---- drivers/counter/counter_rtc_qmsi.c | 15 +++++++---- drivers/dma/dma_qmsi.c | 13 ++++++--- drivers/flash/soc_flash_qmsi.c | 14 +++++++--- drivers/gpio/gpio_dw.c | 15 +++++++---- drivers/gpio/gpio_qmsi.c | 21 ++++++++++----- drivers/gpio/gpio_qmsi_ss.c | 14 +++++++--- drivers/i2c/i2c_qmsi.c | 15 +++++++---- drivers/i2c/i2c_qmsi_ss.c | 14 +++++++--- drivers/interrupt_controller/arcv2_irq_unit.c | 16 +++++++---- drivers/interrupt_controller/ioapic_intr.c | 16 +++++++---- drivers/interrupt_controller/loapic_intr.c | 15 +++++++---- drivers/pwm/pwm_nrfx.c | 11 ++++++-- drivers/pwm/pwm_qmsi.c | 14 ++++++---- drivers/sensor/apds9960/apds9960.c | 27 ++++++++++--------- drivers/sensor/qdec_nrfx/qdec_nrfx.c | 9 ++++--- drivers/serial/uart_nrfx_uart.c | 9 ++++--- drivers/serial/uart_qmsi.c | 15 +++++++---- drivers/spi/spi_intel.c | 15 +++++++---- drivers/timer/loapic_timer.c | 15 +++++++---- drivers/timer/sys_clock_init.c | 4 +-- drivers/watchdog/wdt_qmsi.c | 15 +++++++---- include/device.h | 21 +++++++++++---- include/drivers/system_timer.h | 4 +-- kernel/device.c | 5 +++- samples/sensor/apds9960/src/main.c | 4 +-- subsys/power/device.c | 8 +++--- tests/kernel/device/src/main.c | 5 ++-- 29 files changed, 246 insertions(+), 120 deletions(-) diff --git a/doc/reference/power_management/index.rst b/doc/reference/power_management/index.rst index b1a54283c02..689d3ac0a7c 100644 --- a/doc/reference/power_management/index.rst +++ b/doc/reference/power_management/index.rst @@ -339,7 +339,7 @@ Device Set Power State .. code-block:: c - int device_set_power_state(struct device *device, u32_t device_power_state); + int device_set_power_state(struct device *device, u32_t device_power_state, device_pm_cb cb, void *arg); Calls the :c:func:`device_pm_control()` handler function implemented by the device driver with DEVICE_PM_SET_POWER_STATE command. diff --git a/drivers/counter/counter_qmsi_aonpt.c b/drivers/counter/counter_qmsi_aonpt.c index 738507c615b..9a2320a7530 100644 --- a/drivers/counter/counter_qmsi_aonpt.c +++ b/drivers/counter/counter_qmsi_aonpt.c @@ -196,20 +196,25 @@ static int aonpt_resume_device_from_suspend(struct device *dev) * the *context may include IN data or/and OUT data */ static int aonpt_qmsi_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return aonpt_suspend_device(dev); + ret = aonpt_suspend_device(dev); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return aonpt_resume_device_from_suspend(dev); + ret = aonpt_resume_device_from_suspend(dev); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = aonpt_qmsi_get_power_state(dev); - return 0; } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + + return ret; } #else #define aonpt_qmsi_set_power_state(...) diff --git a/drivers/counter/counter_rtc_qmsi.c b/drivers/counter/counter_rtc_qmsi.c index 8ba3f078f9a..efed73e3f93 100644 --- a/drivers/counter/counter_rtc_qmsi.c +++ b/drivers/counter/counter_rtc_qmsi.c @@ -217,20 +217,25 @@ static int rtc_resume_device(struct device *dev) * the *context may include IN data or/and OUT data */ static int rtc_qmsi_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return rtc_suspend_device(dev); + ret = rtc_suspend_device(dev); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return rtc_resume_device(dev); + ret = rtc_resume_device(dev); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = rtc_qmsi_get_power_state(dev); - return 0; } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + + return ret; } #endif diff --git a/drivers/dma/dma_qmsi.c b/drivers/dma/dma_qmsi.c index ef1a377c68b..c52b28ac8b9 100644 --- a/drivers/dma/dma_qmsi.c +++ b/drivers/dma/dma_qmsi.c @@ -279,19 +279,24 @@ static int dma_resume_device(struct device *dev) } static int dma_qmsi_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return dma_suspend_device(dev); + ret = dma_suspend_device(dev); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return dma_resume_device(dev); + ret = dma_resume_device(dev); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = dma_qmsi_get_power_state(dev); } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + return ret; } #endif diff --git a/drivers/flash/soc_flash_qmsi.c b/drivers/flash/soc_flash_qmsi.c index 8c846c802f6..851c5c9d601 100644 --- a/drivers/flash/soc_flash_qmsi.c +++ b/drivers/flash/soc_flash_qmsi.c @@ -303,19 +303,25 @@ static int flash_qmsi_resume_device(struct device *dev) } static int flash_qmsi_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return flash_qmsi_suspend_device(dev); + ret = flash_qmsi_suspend_device(dev); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return flash_qmsi_resume_device(dev); + ret = flash_qmsi_resume_device(dev); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = flash_qmsi_get_power_state(dev); } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + + return ret; } #else #define flash_qmsi_set_power_state(...) diff --git a/drivers/gpio/gpio_dw.c b/drivers/gpio/gpio_dw.c index 398952ace4a..5c3bc19e4a6 100644 --- a/drivers/gpio/gpio_dw.c +++ b/drivers/gpio/gpio_dw.c @@ -363,19 +363,24 @@ static inline int gpio_dw_resume_from_suspend_port(struct device *port) * the *context may include IN data or/and OUT data */ static int gpio_dw_device_ctrl(struct device *port, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return gpio_dw_suspend_port(port); + ret = gpio_dw_suspend_port(port); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return gpio_dw_resume_from_suspend_port(port); + ret = gpio_dw_resume_from_suspend_port(port); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = gpio_dw_get_power_state(port); - return 0; } - return 0; + + if (cb) { + cb(port, ret, context, arg); + } + return ret; } #else diff --git a/drivers/gpio/gpio_qmsi.c b/drivers/gpio/gpio_qmsi.c index 1db10b9ad49..3cd288f7958 100644 --- a/drivers/gpio/gpio_qmsi.c +++ b/drivers/gpio/gpio_qmsi.c @@ -101,19 +101,24 @@ static int gpio_resume_device_from_suspend(struct device *dev) * the *context may include IN data or/and OUT data */ static int gpio_qmsi_device_ctrl(struct device *port, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return gpio_suspend_device(port); + ret = gpio_suspend_device(port); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return gpio_resume_device_from_suspend(port); + ret = gpio_resume_device_from_suspend(port); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = gpio_qmsi_get_power_state(port); - return 0; } - return 0; + + if (cb) { + cb(port, ret, context, arg); + } + return ret; } #endif @@ -138,7 +143,7 @@ static struct gpio_qmsi_runtime gpio_aon_runtime; * the *context may include IN data or/and OUT data */ static int gpio_aon_device_ctrl(struct device *port, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { u32_t device_pm_state = *(u32_t *)context; @@ -150,6 +155,10 @@ static int gpio_aon_device_ctrl(struct device *port, u32_t ctrl_command, } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = gpio_qmsi_get_power_state(port); } + + if (cb) { + cb(port, 0, context, arg); + } return 0; } #endif diff --git a/drivers/gpio/gpio_qmsi_ss.c b/drivers/gpio/gpio_qmsi_ss.c index f1758860375..352f55ac822 100644 --- a/drivers/gpio/gpio_qmsi_ss.c +++ b/drivers/gpio/gpio_qmsi_ss.c @@ -85,18 +85,24 @@ static int ss_gpio_resume_device_from_suspend(struct device *dev) * the *context may include IN data or/and OUT data */ static int ss_gpio_qmsi_device_ctrl(struct device *port, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return ss_gpio_suspend_device(port); + ret = ss_gpio_suspend_device(port); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return ss_gpio_resume_device_from_suspend(port); + ret = ss_gpio_resume_device_from_suspend(port); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = ss_gpio_qmsi_get_power_state(port); } - return 0; + if (cb) { + cb(port, ret, context, arg); + } + + return ret; } #else #define ss_gpio_qmsi_set_power_state(...) diff --git a/drivers/i2c/i2c_qmsi.c b/drivers/i2c/i2c_qmsi.c index 16099992545..2428ee4909b 100644 --- a/drivers/i2c/i2c_qmsi.c +++ b/drivers/i2c/i2c_qmsi.c @@ -92,20 +92,25 @@ static int i2c_resume_device_from_suspend(struct device *dev) * the *context may include IN data or/and OUT data */ static int i2c_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return i2c_suspend_device(dev); + ret = i2c_suspend_device(dev); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return i2c_resume_device_from_suspend(dev); + ret = i2c_resume_device_from_suspend(dev); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = i2c_qmsi_get_power_state(dev); - return 0; } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + + return ret; } #else #define i2c_qmsi_set_power_state(...) diff --git a/drivers/i2c/i2c_qmsi_ss.c b/drivers/i2c/i2c_qmsi_ss.c index 6eb0908e113..2881aa4b0f4 100644 --- a/drivers/i2c/i2c_qmsi_ss.c +++ b/drivers/i2c/i2c_qmsi_ss.c @@ -89,19 +89,25 @@ static int ss_i2c_resume_device_from_suspend(struct device *dev) * the *context may include IN data or/and OUT data */ static int ss_i2c_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return ss_i2c_suspend_device(dev); + ret = ss_i2c_suspend_device(dev); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return ss_i2c_resume_device_from_suspend(dev); + ret = ss_i2c_resume_device_from_suspend(dev); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = ss_i2c_qmsi_get_power_state(dev); } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + + return ret; } #else #define ss_i2c_qmsi_set_power_state(...) diff --git a/drivers/interrupt_controller/arcv2_irq_unit.c b/drivers/interrupt_controller/arcv2_irq_unit.c index ca5e999b10d..49245bfcacf 100644 --- a/drivers/interrupt_controller/arcv2_irq_unit.c +++ b/drivers/interrupt_controller/arcv2_irq_unit.c @@ -187,19 +187,25 @@ static int _arc_v2_irq_unit_get_state(struct device *dev) * the *context may include IN data or/and OUT data */ static int _arc_v2_irq_unit_device_ctrl(struct device *device, - u32_t ctrl_command, void *context) + u32_t ctrl_command, void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return _arc_v2_irq_unit_suspend(device); + ret = _arc_v2_irq_unit_suspend(device); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return _arc_v2_irq_unit_resume(device); + ret = _arc_v2_irq_unit_resume(device); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = _arc_v2_irq_unit_get_state(device); - return 0; } - return 0; + + if (cb) { + cb(device, ret, context, arg); + } + + return ret; } SYS_DEVICE_DEFINE("arc_v2_irq_unit", _arc_v2_irq_unit_init, diff --git a/drivers/interrupt_controller/ioapic_intr.c b/drivers/interrupt_controller/ioapic_intr.c index ea9e99cd41f..1536482c3d7 100644 --- a/drivers/interrupt_controller/ioapic_intr.c +++ b/drivers/interrupt_controller/ioapic_intr.c @@ -254,19 +254,25 @@ int ioapic_resume_from_suspend(struct device *port) * the *context may include IN data or/and OUT data */ static int ioapic_device_ctrl(struct device *device, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return ioapic_suspend(device); + ret = ioapic_suspend(device); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return ioapic_resume_from_suspend(device); + ret = ioapic_resume_from_suspend(device); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = ioapic_device_power_state; - return 0; } - return 0; + + if (cb) { + cb(device, ret, context, arg); + } + + return ret; } diff --git a/drivers/interrupt_controller/loapic_intr.c b/drivers/interrupt_controller/loapic_intr.c index 0c54023dacf..0952dad2b43 100644 --- a/drivers/interrupt_controller/loapic_intr.c +++ b/drivers/interrupt_controller/loapic_intr.c @@ -486,20 +486,25 @@ int loapic_resume(struct device *port) * the *context may include IN data or/and OUT data */ static int loapic_device_ctrl(struct device *port, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return loapic_suspend(port); + ret = loapic_suspend(port); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return loapic_resume(port); + ret = loapic_resume(port); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = loapic_device_power_state; - return 0; } - return 0; + if (cb) { + cb(port, ret, context, arg); + } + + return ret; } SYS_DEVICE_DEFINE("loapic", _loapic_init, loapic_device_ctrl, PRE_KERNEL_1, diff --git a/drivers/pwm/pwm_nrfx.c b/drivers/pwm/pwm_nrfx.c index 8acd6fef681..26702cb6a9e 100644 --- a/drivers/pwm/pwm_nrfx.c +++ b/drivers/pwm/pwm_nrfx.c @@ -321,11 +321,18 @@ static int pwm_nrfx_pm_control(struct device *dev, #define PWM_NRFX_PM_CONTROL(idx) \ static int pwm_##idx##_nrfx_pm_control(struct device *dev, \ u32_t ctrl_command, \ - void *context) \ + void *context, \ + device_pm_cb cb, \ + void *arg) \ { \ static u32_t current_state = DEVICE_PM_ACTIVE_STATE; \ - return pwm_nrfx_pm_control(dev, ctrl_command, context, \ + int ret = 0; \ + ret = pwm_nrfx_pm_control(dev, ctrl_command, context, \ ¤t_state); \ + if (cb) { \ + cb(dev, ret, context, arg); \ + } \ + return ret; \ } #else diff --git a/drivers/pwm/pwm_qmsi.c b/drivers/pwm/pwm_qmsi.c index 3243b9d41dd..f65c96ba53a 100644 --- a/drivers/pwm/pwm_qmsi.c +++ b/drivers/pwm/pwm_qmsi.c @@ -247,20 +247,24 @@ static int pwm_qmsi_resume_from_suspend(struct device *dev) * the *context may include IN data or/and OUT data */ static int pwm_qmsi_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return pwm_qmsi_suspend(dev); + ret = pwm_qmsi_suspend(dev); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return pwm_qmsi_resume_from_suspend(dev); + ret = pwm_qmsi_resume_from_suspend(dev); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = pwm_qmsi_get_power_state(dev); - return 0; } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + return ret; } #endif diff --git a/drivers/sensor/apds9960/apds9960.c b/drivers/sensor/apds9960/apds9960.c index eea49c5338c..d280836ee09 100644 --- a/drivers/sensor/apds9960/apds9960.c +++ b/drivers/sensor/apds9960/apds9960.c @@ -375,9 +375,10 @@ static int apds9960_init_interrupt(struct device *dev) #ifdef CONFIG_DEVICE_POWER_MANAGEMENT static int apds9960_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { struct apds9960_data *data = dev->driver_data; + int ret = 0; if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { u32_t device_pm_state = *(u32_t *)context; @@ -387,30 +388,32 @@ static int apds9960_device_ctrl(struct device *dev, u32_t ctrl_command, APDS9960_ENABLE_REG, APDS9960_ENABLE_PON, APDS9960_ENABLE_PON)) { - return -EIO; + ret = -EIO; } - return 0; - } + } else { - if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, + if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_ENABLE_REG, APDS9960_ENABLE_PON, 0)) { - return -EIO; - } + ret = -EIO; + } - if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, + if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_AICLEAR_REG, 0)) { - return -EIO; + ret = -EIO; + } } - return 0; - } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = DEVICE_PM_ACTIVE_STATE; } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + + return ret; } #endif diff --git a/drivers/sensor/qdec_nrfx/qdec_nrfx.c b/drivers/sensor/qdec_nrfx/qdec_nrfx.c index 4d08c3870f9..935cbdf7db6 100644 --- a/drivers/sensor/qdec_nrfx/qdec_nrfx.c +++ b/drivers/sensor/qdec_nrfx/qdec_nrfx.c @@ -271,9 +271,8 @@ static int qdec_nrfx_pm_set_state(struct qdec_nrfx_data *data, return 0; } -static int qdec_nrfx_pm_control(struct device *dev, - u32_t ctrl_command, - void *context) +static int qdec_nrfx_pm_control(struct device *dev, u32_t ctrl_command, + void *context, device_pm_cb cb, void *arg) { struct qdec_nrfx_data *data = &qdec_nrfx_data; int err; @@ -294,6 +293,10 @@ static int qdec_nrfx_pm_control(struct device *dev, break; } + if (cb) { + cb(dev, err, context, arg); + } + return err; } diff --git a/drivers/serial/uart_nrfx_uart.c b/drivers/serial/uart_nrfx_uart.c index ea4b823f83f..03bcc3ed244 100644 --- a/drivers/serial/uart_nrfx_uart.c +++ b/drivers/serial/uart_nrfx_uart.c @@ -964,9 +964,8 @@ static void uart_nrfx_set_power_state(u32_t new_state) } } -static int uart_nrfx_pm_control(struct device *dev, - u32_t ctrl_command, - void *context) +static int uart_nrfx_pm_control(struct device *dev, u32_t ctrl_command, + void *context, device_pm_cb cb, void *arg) { static u32_t current_state = DEVICE_PM_ACTIVE_STATE; @@ -982,6 +981,10 @@ static int uart_nrfx_pm_control(struct device *dev, *((u32_t *)context) = current_state; } + if (cb) { + cb(dev, 0, context, arg); + } + return 0; } #endif /* CONFIG_DEVICE_POWER_MANAGEMENT */ diff --git a/drivers/serial/uart_qmsi.c b/drivers/serial/uart_qmsi.c index da80b10f5b2..9963c966573 100644 --- a/drivers/serial/uart_qmsi.c +++ b/drivers/serial/uart_qmsi.c @@ -110,20 +110,25 @@ static int uart_resume_device_from_suspend(struct device *dev) * the *context may include IN data or/and OUT data */ static int uart_qmsi_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return uart_suspend_device(dev); + ret = uart_suspend_device(dev); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return uart_resume_device_from_suspend(dev); + ret = uart_resume_device_from_suspend(dev); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = uart_qmsi_get_power_state(dev); - return 0; } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + + return ret; } #endif /* CONFIG_DEVICE_POWER_MANAGEMENT */ diff --git a/drivers/spi/spi_intel.c b/drivers/spi/spi_intel.c index c0539b6a001..035fcedd9ed 100644 --- a/drivers/spi/spi_intel.c +++ b/drivers/spi/spi_intel.c @@ -390,20 +390,25 @@ static int spi_intel_resume_from_suspend(struct device *dev) * the *context may include IN data or/and OUT data */ static int spi_intel_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return spi_intel_suspend(dev); + ret = spi_intel_suspend(dev); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return spi_intel_resume_from_suspend(dev); + ret = spi_intel_resume_from_suspend(dev); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = spi_intel_get_power_state(dev); - return 0; } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + + return ret; } #else #define spi_intel_set_power_state(...) diff --git a/drivers/timer/loapic_timer.c b/drivers/timer/loapic_timer.c index d251fa4adc5..d0818fde784 100644 --- a/drivers/timer/loapic_timer.c +++ b/drivers/timer/loapic_timer.c @@ -737,20 +737,25 @@ static int sys_clock_resume(struct device *dev) * the *context may include IN data or/and OUT data */ int z_clock_device_ctrl(struct device *port, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return sys_clock_suspend(port); + ret = sys_clock_suspend(port); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return sys_clock_resume(port); + ret = sys_clock_resume(port); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = loapic_timer_device_power_state; - return 0; } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + + return ret; } #endif diff --git a/drivers/timer/sys_clock_init.c b/drivers/timer/sys_clock_init.c index b8146603214..4312470ab28 100644 --- a/drivers/timer/sys_clock_init.c +++ b/drivers/timer/sys_clock_init.c @@ -28,8 +28,8 @@ int __weak z_clock_driver_init(struct device *device) return 0; } -int __weak z_clock_device_ctrl(struct device *device, - u32_t ctrl_command, void *context) +int __weak z_clock_device_ctrl(struct device *device, u32_t ctrl_command, + void *context, device_pm_cb cb, void *arg) { return 0; } diff --git a/drivers/watchdog/wdt_qmsi.c b/drivers/watchdog/wdt_qmsi.c index 610b1b046c5..f5217cec46b 100644 --- a/drivers/watchdog/wdt_qmsi.c +++ b/drivers/watchdog/wdt_qmsi.c @@ -193,20 +193,25 @@ static int wdt_resume_device_from_suspend(struct device *dev) * the *context may include IN data or/and OUT data */ static int wdt_qmsi_device_ctrl(struct device *dev, u32_t ctrl_command, - void *context) + void *context, device_pm_cb cb, void *arg) { + int ret = 0; + if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return wdt_suspend_device(dev); + ret = wdt_suspend_device(dev); } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return wdt_resume_device_from_suspend(dev); + ret = wdt_resume_device_from_suspend(dev); } } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = wdt_qmsi_get_power_state(dev); - return 0; } - return 0; + if (cb) { + cb(dev, ret, context, arg); + } + + return ret; } #else #define wdt_qmsi_set_power_state(...) diff --git a/include/device.h b/include/device.h index f5ec7a3efdb..95351b0ff4f 100644 --- a/include/device.h +++ b/include/device.h @@ -208,6 +208,8 @@ extern "C" { struct device; +typedef void (*device_pm_cb)(struct device *dev, + int status, void *context, void *arg); /** * @brief Static device information (In ROM) Per driver instance @@ -221,7 +223,7 @@ struct device_config { int (*init)(struct device *device); #ifdef CONFIG_DEVICE_POWER_MANAGEMENT int (*device_pm_control)(struct device *device, u32_t command, - void *context); + void *context, device_pm_cb cb, void *arg); #endif const void *config_info; }; @@ -364,11 +366,16 @@ void device_busy_clear(struct device *busy_dev); * @param unused_device Unused * @param unused_ctrl_command Unused * @param unused_context Unused + * @param cb Unused + * @param unused_arg Unused * * @retval 0 Always returns 0 */ int device_pm_control_nop(struct device *unused_device, - u32_t unused_ctrl_command, void *unused_context); + u32_t unused_ctrl_command, + void *unused_context, + device_pm_cb cb, + void *unused_arg); /** * @brief Call the set power state function of a device * @@ -377,16 +384,19 @@ int device_pm_control_nop(struct device *unused_device, * Note that devices may support just some of the device power states * @param device Pointer to device structure of the driver instance. * @param device_power_state Device power state to be set + * @param cb Callback function to notify device power status + * @param arg Caller passed argument to callback function * * @retval 0 If successful. * @retval Errno Negative errno code if failure. */ static inline int device_set_power_state(struct device *device, - u32_t device_power_state) + u32_t device_power_state, + device_pm_cb cb, void *arg) { return device->config->device_pm_control(device, DEVICE_PM_SET_POWER_STATE, - &device_power_state); + &device_power_state, cb, arg); } /** @@ -407,7 +417,8 @@ static inline int device_get_power_state(struct device *device, { return device->config->device_pm_control(device, DEVICE_PM_GET_POWER_STATE, - device_power_state); + device_power_state, + NULL, NULL); } /** diff --git a/include/drivers/system_timer.h b/include/drivers/system_timer.h index cf7b1113c87..508c4e09c82 100644 --- a/include/drivers/system_timer.h +++ b/include/drivers/system_timer.h @@ -40,8 +40,8 @@ extern int z_clock_driver_init(struct device *device); * management. It is a weak symbol that will be implemented as a noop * if undefined in the clock driver. */ -extern int z_clock_device_ctrl(struct device *device, - u32_t ctrl_command, void *context); +extern int z_clock_device_ctrl(struct device *device, u32_t ctrl_command, + void *context, device_pm_cb cb, void *arg); /** * @brief Set system clock timeout diff --git a/kernel/device.c b/kernel/device.c index 47ca592f3c0..85d5b1604f2 100644 --- a/kernel/device.c +++ b/kernel/device.c @@ -110,7 +110,10 @@ Z_SYSCALL_HANDLER(device_get_binding, name) #ifdef CONFIG_DEVICE_POWER_MANAGEMENT int device_pm_control_nop(struct device *unused_device, - u32_t unused_ctrl_command, void *unused_context) + u32_t unused_ctrl_command, + void *unused_context, + device_pm_cb cb, + void *unused_arg) { return 0; } diff --git a/samples/sensor/apds9960/src/main.c b/samples/sensor/apds9960/src/main.c index 389f227eba7..f513a184615 100644 --- a/samples/sensor/apds9960/src/main.c +++ b/samples/sensor/apds9960/src/main.c @@ -79,11 +79,11 @@ void main(void) u32_t p_state; p_state = DEVICE_PM_LOW_POWER_STATE; - device_set_power_state(dev, p_state); + device_set_power_state(dev, p_state, NULL, NULL); printk("set low power state for 2s\n"); k_sleep(2000); p_state = DEVICE_PM_ACTIVE_STATE; - device_set_power_state(dev, p_state); + device_set_power_state(dev, p_state, NULL, NULL); #endif } } diff --git a/subsys/power/device.c b/subsys/power/device.c index 87f37e92731..2b5698ec80c 100644 --- a/subsys/power/device.c +++ b/subsys/power/device.c @@ -54,7 +54,8 @@ int sys_pm_suspend_devices(void) * and set the device states accordingly. */ device_retval[i] = device_set_power_state(&pm_device_list[idx], - DEVICE_PM_SUSPEND_STATE); + DEVICE_PM_SUSPEND_STATE, + NULL, NULL); if (device_retval[i]) { LOG_ERR("%s suspend operation failed\n", pm_device_list[idx].config->name); @@ -71,7 +72,8 @@ int sys_pm_force_suspend_devices(void) int idx = device_ordered_list[i]; device_retval[i] = device_set_power_state(&pm_device_list[idx], - DEVICE_PM_FORCE_SUSPEND_STATE); + DEVICE_PM_FORCE_SUSPEND_STATE, + NULL, NULL); if (device_retval[i]) { LOG_ERR("%s force suspend operation failed\n", pm_device_list[idx].config->name); @@ -91,7 +93,7 @@ void sys_pm_resume_devices(void) int idx = device_ordered_list[i]; device_set_power_state(&pm_device_list[idx], - DEVICE_PM_ACTIVE_STATE); + DEVICE_PM_ACTIVE_STATE, NULL, NULL); } } } diff --git a/tests/kernel/device/src/main.c b/tests/kernel/device/src/main.c index 2798181a325..620b3f8f529 100644 --- a/tests/kernel/device/src/main.c +++ b/tests/kernel/device/src/main.c @@ -124,7 +124,7 @@ void test_dummy_device_pm(void) zassert_true((busy == 0), NULL); /* Set device state to DEVICE_PM_ACTIVE_STATE */ - ret = device_set_power_state(dev, DEVICE_PM_ACTIVE_STATE); + ret = device_set_power_state(dev, DEVICE_PM_ACTIVE_STATE, NULL, NULL); zassert_true((ret == 0), "Unable to set active state to device"); device_busy_set(dev); @@ -141,7 +141,8 @@ void test_dummy_device_pm(void) zassert_true((busy == 0), NULL); /* Set device state to DEVICE_PM_FORCE_SUSPEND_STATE */ - ret = device_set_power_state(dev, DEVICE_PM_FORCE_SUSPEND_STATE); + ret = device_set_power_state(dev, + DEVICE_PM_FORCE_SUSPEND_STATE, NULL, NULL); zassert_true((ret == 0), "Unable to force suspend device"); build_suspend_device_list();