blob: 5f231dda6b70a9f75918d2ce9644f2d1d805a551 [file] [log] [blame]
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <sys/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);