samples: power: Add test for device Idle PM
Added test for Device Idle Power Management to invoke
device_pm_get/put API's.
Signed-off-by: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
diff --git a/CODEOWNERS b/CODEOWNERS
index 61c0fea..c54b250 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -228,6 +228,7 @@
/samples/net/sockets/ @jukkar @tbursztyka @pfalcon
/samples/sensor/ @bogdan-davidoaia
/samples/subsys/usb/ @jfischer-phytec-iot @finikorg
+/samples/subsys/power/ @ramakrishnapallala @pizi-nordic
/scripts/coccicheck @himanshujha199640 @JuliaLawall
/scripts/coccinelle/ @himanshujha199640 @JuliaLawall
/scripts/elf_helper.py @andrewboie
diff --git a/samples/subsys/power/device_pm/CMakeLists.txt b/samples/subsys/power/device_pm/CMakeLists.txt
new file mode 100644
index 0000000..9c27f92
--- /dev/null
+++ b/samples/subsys/power/device_pm/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.13.1)
+include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
+project(device)
+
+FILE(GLOB app_sources src/*.c)
+target_sources(app PRIVATE ${app_sources})
diff --git a/samples/subsys/power/device_pm/prj.conf b/samples/subsys/power/device_pm/prj.conf
new file mode 100644
index 0000000..98088b4
--- /dev/null
+++ b/samples/subsys/power/device_pm/prj.conf
@@ -0,0 +1,3 @@
+CONFIG_SYS_POWER_MANAGEMENT=y
+CONFIG_DEVICE_POWER_MANAGEMENT=y
+CONFIG_DEVICE_IDLE_PM=y
diff --git a/samples/subsys/power/device_pm/sample.yaml b/samples/subsys/power/device_pm/sample.yaml
new file mode 100644
index 0000000..506ed98
--- /dev/null
+++ b/samples/subsys/power/device_pm/sample.yaml
@@ -0,0 +1,6 @@
+sample:
+ name: Device Idle Power Management
+tests:
+ ospm.dev_idle_pm:
+ platform_whitelist: nrf52840_pca10056 nrf52_pca10040
+ tags: power
diff --git a/samples/subsys/power/device_pm/src/dummy_driver.c b/samples/subsys/power/device_pm/src/dummy_driver.c
new file mode 100644
index 0000000..6d64829
--- /dev/null
+++ b/samples/subsys/power/device_pm/src/dummy_driver.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <misc/printk.h>
+#include "dummy_parent.h"
+#include "dummy_driver.h"
+
+static struct k_poll_event async_evt;
+u32_t device_power_state;
+static struct device *parent;
+
+static int dummy_open(struct device *dev)
+{
+ int ret;
+ int signaled = 0, result;
+
+ printk("open()\n");
+
+ /* Make sure parent is resumed */
+ ret = device_pm_get_sync(parent);
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = device_pm_get(dev);
+ if (ret < 0) {
+ return ret;
+ }
+
+ printk("Async wakeup request queued\n");
+
+ do {
+ (void)k_poll(&async_evt, 1, K_FOREVER);
+ k_poll_signal_check(&dev->config->pm->signal,
+ &signaled, &result);
+ } while (!signaled);
+
+ async_evt.state = K_POLL_STATE_NOT_READY;
+ k_poll_signal_reset(&dev->config->pm->signal);
+
+ if (result == DEVICE_PM_ACTIVE_STATE) {
+ printk("Dummy device resumed\n");
+ ret = 0;
+ } else {
+ printk("Dummy device Not resumed\n");
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int dummy_read(struct device *dev, u32_t *val)
+{
+ struct dummy_parent_api *api;
+ int ret;
+
+ printk("read()\n");
+
+ api = (struct dummy_parent_api *)parent->driver_api;
+ ret = api->transfer(parent, DUMMY_PARENT_RD, val);
+ return ret;
+}
+
+static int dummy_write(struct device *dev, u32_t val)
+{
+ struct dummy_parent_api *api;
+ int ret;
+
+ printk("write()\n");
+ api = (struct dummy_parent_api *)parent->driver_api;
+ ret = api->transfer(parent, DUMMY_PARENT_WR, &val);
+ return ret;
+}
+
+static int dummy_close(struct device *dev)
+{
+ int ret;
+
+ printk("close()\n");
+ ret = device_pm_put_sync(dev);
+ if (ret == 1) {
+ printk("Async suspend request ququed\n");
+ }
+
+ /* Parent can be suspended */
+ if (parent) {
+ device_pm_put(parent);
+ }
+
+ return ret;
+}
+
+static u32_t dummy_get_power_state(struct device *dev)
+{
+ return device_power_state;
+}
+
+static int dummy_suspend(struct device *dev)
+{
+ printk("child suspending..\n");
+ device_power_state = DEVICE_PM_SUSPEND_STATE;
+
+ return 0;
+}
+
+static int dummy_resume_from_suspend(struct device *dev)
+{
+ printk("child resuming..\n");
+ device_power_state = DEVICE_PM_ACTIVE_STATE;
+
+ return 0;
+}
+
+static int dummy_device_pm_ctrl(struct device *dev, u32_t ctrl_command,
+ void *context, device_pm_cb cb, void *arg)
+{
+ int ret = 0;
+
+ switch (ctrl_command) {
+ case DEVICE_PM_SET_POWER_STATE:
+ if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
+ ret = dummy_resume_from_suspend(dev);
+ } else {
+ ret = dummy_suspend(dev);
+ }
+ break;
+ case DEVICE_PM_GET_POWER_STATE:
+ *((u32_t *)context) = dummy_get_power_state(dev);
+ break;
+ default:
+ ret = -EINVAL;
+
+ }
+
+ cb(dev, ret, context, arg);
+
+ return ret;
+}
+
+static const struct dummy_driver_api funcs = {
+ .open = dummy_open,
+ .read = dummy_read,
+ .write = dummy_write,
+ .close = dummy_close,
+};
+
+int dummy_init(struct device *dev)
+{
+ parent = device_get_binding(DUMMY_PARENT_NAME);
+ if (!parent) {
+ printk("parent not found\n");
+ }
+
+ device_pm_enable(dev);
+ device_power_state = DEVICE_PM_ACTIVE_STATE;
+
+ k_poll_event_init(&async_evt, K_POLL_TYPE_SIGNAL,
+ K_POLL_MODE_NOTIFY_ONLY, &dev->config->pm->signal);
+ return 0;
+}
+
+DEVICE_DEFINE(dummy_driver, DUMMY_DRIVER_NAME, &dummy_init,
+ dummy_device_pm_ctrl, NULL, NULL, APPLICATION,
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs);
diff --git a/samples/subsys/power/device_pm/src/dummy_driver.h b/samples/subsys/power/device_pm/src/dummy_driver.h
new file mode 100644
index 0000000..0fc5994
--- /dev/null
+++ b/samples/subsys/power/device_pm/src/dummy_driver.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <device.h>
+#define DUMMY_DRIVER_NAME "dummy_driver"
+
+typedef int (*dummy_api_open_t)(struct device *dev);
+
+typedef int (*dummy_api_read_t)(struct device *dev,
+ u32_t *val);
+typedef int (*dummy_api_write_t)(struct device *dev,
+ u32_t val);
+typedef int (*dummy_api_close_t)(struct device *dev);
+
+struct dummy_driver_api {
+ dummy_api_open_t open;
+ dummy_api_read_t read;
+ dummy_api_write_t write;
+ dummy_api_close_t close;
+};
diff --git a/samples/subsys/power/device_pm/src/dummy_parent.c b/samples/subsys/power/device_pm/src/dummy_parent.c
new file mode 100644
index 0000000..a47fdce
--- /dev/null
+++ b/samples/subsys/power/device_pm/src/dummy_parent.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <misc/printk.h>
+#include "dummy_parent.h"
+
+static u32_t store_value;
+u32_t parent_power_state;
+
+static int dummy_transfer(struct device *dev, u32_t cmd, u32_t *val)
+{
+ printk("transfer()\n");
+
+ if (cmd == DUMMY_PARENT_WR) {
+ store_value = *val;
+ } else {
+ *val = store_value;
+ }
+
+ return 0;
+}
+
+static u32_t dummy_get_power_state(struct device *dev)
+{
+ return parent_power_state;
+}
+
+static int dummy_suspend(struct device *dev)
+{
+ printk("parent suspending..\n");
+ parent_power_state = DEVICE_PM_SUSPEND_STATE;
+
+ return 0;
+}
+
+static int dummy_resume_from_suspend(struct device *dev)
+{
+ printk("parent resuming..\n");
+ parent_power_state = DEVICE_PM_ACTIVE_STATE;
+
+ return 0;
+}
+
+static int dummy_parent_pm_ctrl(struct device *dev, u32_t ctrl_command,
+ void *context, device_pm_cb cb, void *arg)
+{
+ int ret = 0;
+
+ switch (ctrl_command) {
+ case DEVICE_PM_SET_POWER_STATE:
+ if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
+ ret = dummy_resume_from_suspend(dev);
+ } else {
+ ret = dummy_suspend(dev);
+ }
+ break;
+ case DEVICE_PM_GET_POWER_STATE:
+ *((u32_t *)context) = dummy_get_power_state(dev);
+ break;
+ default:
+ ret = -EINVAL;
+
+ }
+
+ cb(dev, ret, context, arg);
+ return ret;
+}
+
+static const struct dummy_parent_api funcs = {
+ .transfer = dummy_transfer,
+};
+
+int dummy_parent_init(struct device *dev)
+{
+ device_pm_enable(dev);
+ parent_power_state = DEVICE_PM_ACTIVE_STATE;
+ return 0;
+}
+
+DEVICE_DEFINE(dummy_parent, DUMMY_PARENT_NAME, &dummy_parent_init,
+ dummy_parent_pm_ctrl, NULL, NULL, POST_KERNEL,
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs);
diff --git a/samples/subsys/power/device_pm/src/dummy_parent.h b/samples/subsys/power/device_pm/src/dummy_parent.h
new file mode 100644
index 0000000..77195b5
--- /dev/null
+++ b/samples/subsys/power/device_pm/src/dummy_parent.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <device.h>
+#define DUMMY_PARENT_NAME "dummy_parent"
+
+#define DUMMY_PARENT_RD 0
+#define DUMMY_PARENT_WR 1
+
+typedef int (*dummy_api_transfer_t)(struct device *dev, u32_t cmd, u32_t *val);
+
+struct dummy_parent_api {
+ dummy_api_transfer_t transfer;
+};
diff --git a/samples/subsys/power/device_pm/src/main.c b/samples/subsys/power/device_pm/src/main.c
new file mode 100644
index 0000000..c30057b
--- /dev/null
+++ b/samples/subsys/power/device_pm/src/main.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <misc/printk.h>
+#include "dummy_driver.h"
+
+/* Application main Thread */
+void main(void)
+{
+ struct device *dev;
+ struct dummy_driver_api *api;
+ int ret, val;
+
+ printk("Device PM sample app start\n");
+ dev = device_get_binding(DUMMY_DRIVER_NAME);
+ api = (struct dummy_driver_api *)dev->driver_api;
+ ret = api->open(dev);
+ val = 10;
+ ret = api->write(dev, val);
+ ret = api->read(dev, &val);
+ ret = api->close(dev);
+ printk("Device PM sample app complete\n");
+}