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();