power_mgmt: Update sample and drivers according to new pm device API
Update the power sample and drivers with the new device driver power management API using the existing logic Jira: ZEP-954 Change-Id: Idd94232e458767635973e94e9fc673c01612c1e2 Signed-off-by: Amir Kaplan <amir.kaplan@intel.com>
This commit is contained in:
parent
d305da61e9
commit
c490219d1e
23 changed files with 1096 additions and 531 deletions
|
@ -31,6 +31,9 @@ static counter_callback_t user_cb;
|
|||
|
||||
struct aon_data {
|
||||
struct nano_sem sem;
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_AON_API_REENTRANCY
|
||||
|
@ -161,6 +164,63 @@ static struct counter_driver_api aon_timer_qmsi_api = {
|
|||
.set_alarm = aon_timer_qmsi_set_alarm,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static uint32_t int_aonpt_mask_save;
|
||||
|
||||
static void aonpt_qmsi_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct aon_data *context = dev->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
|
||||
static uint32_t aonpt_qmsi_get_power_state(struct device *dev)
|
||||
{
|
||||
struct aon_data *context = dev->driver_data;
|
||||
|
||||
return context->device_power_state;
|
||||
}
|
||||
|
||||
static int aonpt_suspend_device(struct device *dev)
|
||||
{
|
||||
int_aonpt_mask_save = QM_SCSS_INT->int_aon_timer_mask;
|
||||
|
||||
aonpt_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aonpt_resume_device_from_suspend(struct device *dev)
|
||||
{
|
||||
QM_SCSS_INT->int_aon_timer_mask = int_aonpt_mask_save;
|
||||
|
||||
aonpt_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int aonpt_qmsi_device_ctrl(struct device *dev, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return aonpt_suspend_device(dev);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return aonpt_resume_device_from_suspend(dev);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = aonpt_qmsi_get_power_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define aonpt_qmsi_set_power_state(...)
|
||||
#endif
|
||||
|
||||
static int aon_timer_init(struct device *dev)
|
||||
{
|
||||
dev->driver_api = &aon_timer_qmsi_api;
|
||||
|
@ -176,37 +236,16 @@ static int aon_timer_init(struct device *dev)
|
|||
|
||||
aon_reentrancy_init(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static uint32_t int_aonpt_mask_save;
|
||||
|
||||
static int aonpt_suspend_device(struct device *dev, int pm_policy)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
int_aonpt_mask_save = QM_SCSS_INT->int_aon_timer_mask;
|
||||
}
|
||||
aonpt_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aonpt_resume_device(struct device *dev, int pm_policy)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
QM_SCSS_INT->int_aon_timer_mask = int_aonpt_mask_save;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(aon_timer, aonpt_suspend_device, aonpt_resume_device);
|
||||
|
||||
DEVICE_AND_API_INIT_PM(aon_timer, CONFIG_AON_TIMER_QMSI_DEV_NAME,
|
||||
aon_timer_init, DEVICE_PM_OPS_GET(aon_timer), AONPT_CONTEXT,
|
||||
NULL, SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
(void *)&aon_timer_qmsi_api);
|
||||
DEVICE_DEFINE(aon_timer, CONFIG_AON_TIMER_QMSI_DEV_NAME, aon_timer_init,
|
||||
aonpt_qmsi_device_ctrl, AONPT_CONTEXT, NULL, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
(void *)&aon_timer_qmsi_api);
|
||||
|
||||
static void aonpt_int_callback(void *user_data)
|
||||
{
|
||||
|
|
|
@ -336,19 +336,57 @@ static inline int gpio_dw_disable_callback(struct device *port, int access_op,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static inline int gpio_dw_suspend_port(struct device *port, int pm_policy)
|
||||
static void gpio_dw_set_power_state(struct device *port, uint32_t power_state)
|
||||
{
|
||||
struct gpio_dw_runtime *context = port->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
|
||||
static uint32_t gpio_dw_get_power_state(struct device *port)
|
||||
{
|
||||
struct gpio_dw_runtime *context = port->driver_data;
|
||||
|
||||
return context->device_power_state;
|
||||
}
|
||||
|
||||
static inline int gpio_dw_suspend_port(struct device *port)
|
||||
{
|
||||
_gpio_dw_clock_off(port);
|
||||
gpio_dw_set_power_state(port, DEVICE_PM_SUSPEND_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpio_dw_resume_port(struct device *port, int pm_policy)
|
||||
static inline int gpio_dw_resume_from_suspend_port(struct device *port)
|
||||
{
|
||||
_gpio_dw_clock_on(port);
|
||||
|
||||
gpio_dw_set_power_state(port, DEVICE_PM_ACTIVE_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int gpio_dw_device_ctrl(struct device *port, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return gpio_dw_suspend_port(port);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return gpio_dw_resume_from_suspend_port(port);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = gpio_dw_get_power_state(port);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define gpio_dw_set_power_state(...)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOC_QUARK_SE_C1000) || defined(CONFIG_SOC_QUARK_D2000)
|
||||
|
@ -456,6 +494,8 @@ int gpio_dw_initialize(struct device *port)
|
|||
config->config_func(port);
|
||||
}
|
||||
|
||||
gpio_dw_set_power_state(port, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -491,13 +531,9 @@ struct gpio_dw_config gpio_config_0 = {
|
|||
struct gpio_dw_runtime gpio_0_runtime;
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
struct device_pm_ops gpio_dev_pm_ops = {
|
||||
.suspend = gpio_dw_suspend_port,
|
||||
.resume = gpio_dw_resume_port
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT_PM(gpio_dw_0, CONFIG_GPIO_DW_0_NAME, gpio_dw_initialize,
|
||||
&gpio_dev_pm_ops, &gpio_0_runtime, &gpio_config_0,
|
||||
DEVICE_DEFINE(gpio_dw_0, CONFIG_GPIO_DW_0_NAME, gpio_dw_initialize,
|
||||
gpio_dw_device_ctrl, &gpio_0_runtime, &gpio_config_0,
|
||||
SECONDARY, CONFIG_GPIO_DW_INIT_PRIORITY,
|
||||
&api_funcs);
|
||||
#else
|
||||
|
@ -563,8 +599,8 @@ struct gpio_dw_config gpio_dw_config_1 = {
|
|||
struct gpio_dw_runtime gpio_1_runtime;
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
DEVICE_AND_API_INIT_PM(gpio_dw_1, CONFIG_GPIO_DW_1_NAME, gpio_dw_initialize,
|
||||
&gpio_dev_pm_ops, &gpio_1_runtime, &gpio_dw_config_1,
|
||||
DEVICE_DEFINE(gpio_dw_1, CONFIG_GPIO_DW_1_NAME, gpio_dw_initialize,
|
||||
gpio_dw_device_ctrl, &gpio_1_runtime, &gpio_dw_config_1,
|
||||
SECONDARY, CONFIG_GPIO_DW_INIT_PRIORITY,
|
||||
&api_funcs);
|
||||
#else
|
||||
|
@ -629,8 +665,8 @@ struct gpio_dw_config gpio_dw_config_2 = {
|
|||
struct gpio_dw_runtime gpio_2_runtime;
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
DEVICE_AND_API_INIT_PM(gpio_dw_2, CONFIG_GPIO_DW_2_NAME, gpio_dw_initialize,
|
||||
&gpio_dev_pm_ops, &gpio_2_runtime, &gpio_dw_config_2,
|
||||
DEVICE_DEFINE(gpio_dw_2, CONFIG_GPIO_DW_2_NAME, gpio_dw_initialize,
|
||||
gpio_dw_device_ctrl, &gpio_2_runtime, &gpio_dw_config_2,
|
||||
SECONDARY, CONFIG_GPIO_DW_INIT_PRIORITY,
|
||||
&api_funcs);
|
||||
#else
|
||||
|
@ -695,8 +731,8 @@ struct gpio_dw_config gpio_dw_config_3 = {
|
|||
struct gpio_dw_runtime gpio_3_runtime;
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
DEVICE_AND_API_INIT_PM(gpio_dw_3, CONFIG_GPIO_DW_3_NAME, gpio_dw_initialize,
|
||||
&gpio_dev_pm_ops, &gpio_3_runtime, &gpio_dw_config_3,
|
||||
DEVICE_DEFINE(gpio_dw_3, CONFIG_GPIO_DW_3_NAME, gpio_dw_initialize,
|
||||
gpio_dw_device_ctrl, &gpio_3_runtime, &gpio_dw_config_3,
|
||||
SECONDARY, CONFIG_GPIO_DW_INIT_PRIORITY,
|
||||
&api_funcs);
|
||||
#else
|
||||
|
|
|
@ -54,6 +54,9 @@ struct gpio_dw_runtime {
|
|||
struct device *clock;
|
||||
#endif
|
||||
sys_slist_t callbacks;
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -40,6 +40,9 @@ struct gpio_qmsi_runtime {
|
|||
#ifdef CONFIG_GPIO_QMSI_API_REENTRANCY
|
||||
struct nano_sem sem;
|
||||
#endif /* CONFIG_GPIO_QMSI_API_REENTRANCY */
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_GPIO_QMSI_API_REENTRANCY
|
||||
|
@ -80,6 +83,25 @@ static void gpio_critical_region_end(struct device *dev)
|
|||
|
||||
int gpio_qmsi_init(struct device *dev);
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static void gpio_qmsi_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct gpio_qmsi_runtime *context = dev->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
|
||||
static uint32_t gpio_qmsi_get_power_state(struct device *dev)
|
||||
{
|
||||
struct gpio_qmsi_runtime *context = dev->driver_data;
|
||||
|
||||
return context->device_power_state;
|
||||
}
|
||||
#else
|
||||
#define gpio_qmsi_set_power_state(...)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_GPIO_QMSI_0
|
||||
static struct gpio_qmsi_config gpio_0_config = {
|
||||
.gpio = QM_GPIO_0,
|
||||
|
@ -92,48 +114,68 @@ static struct gpio_qmsi_runtime gpio_0_runtime;
|
|||
QM_RW uint32_t save_reg[10];
|
||||
static uint32_t int_gpio_mask_save;
|
||||
|
||||
static int gpio_suspend_device(struct device *dev, int pm_policy)
|
||||
static int gpio_suspend_device(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
int_gpio_mask_save = REG_VAL(&QM_SCSS_INT->int_gpio_mask);
|
||||
save_reg[0] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_dr);
|
||||
save_reg[1] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ddr);
|
||||
save_reg[2] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ctl);
|
||||
save_reg[3] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inten);
|
||||
save_reg[4] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_intmask);
|
||||
save_reg[5] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inttype_level);
|
||||
save_reg[6] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_polarity);
|
||||
save_reg[7] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_debounce);
|
||||
save_reg[8] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_ls_sync);
|
||||
save_reg[9] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_bothedge);
|
||||
}
|
||||
int_gpio_mask_save = REG_VAL(&QM_SCSS_INT->int_gpio_mask);
|
||||
save_reg[0] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_dr);
|
||||
save_reg[1] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ddr);
|
||||
save_reg[2] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ctl);
|
||||
save_reg[3] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inten);
|
||||
save_reg[4] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_intmask);
|
||||
save_reg[5] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inttype_level);
|
||||
save_reg[6] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_polarity);
|
||||
save_reg[7] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_debounce);
|
||||
save_reg[8] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_ls_sync);
|
||||
save_reg[9] = REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_bothedge);
|
||||
|
||||
gpio_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_resume_device(struct device *dev, int pm_policy)
|
||||
static int gpio_resume_device_from_suspend(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_dr) = save_reg[0];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ddr) = save_reg[1];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ctl) = save_reg[2];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inten) = save_reg[3];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_intmask) = save_reg[4];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inttype_level) = save_reg[5];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_polarity) = save_reg[6];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_debounce) = save_reg[7];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_ls_sync) = save_reg[8];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_bothedge) = save_reg[9];
|
||||
REG_VAL(&QM_SCSS_INT->int_gpio_mask) = int_gpio_mask_save;
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_dr) = save_reg[0];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ddr) = save_reg[1];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_swporta_ctl) = save_reg[2];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inten) = save_reg[3];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_intmask) = save_reg[4];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_inttype_level) = save_reg[5];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_polarity) = save_reg[6];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_debounce) = save_reg[7];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_ls_sync) = save_reg[8];
|
||||
REG_VAL(&QM_GPIO[QM_GPIO_0]->gpio_int_bothedge) = save_reg[9];
|
||||
REG_VAL(&QM_SCSS_INT->int_gpio_mask) = int_gpio_mask_save;
|
||||
|
||||
gpio_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int gpio_qmsi_device_ctrl(struct device *port, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return gpio_suspend_device(port);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return gpio_resume_device_from_suspend(port);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = gpio_qmsi_get_power_state(port);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(gpio, gpio_suspend_device, gpio_resume_device);
|
||||
|
||||
DEVICE_INIT_PM(gpio_0, CONFIG_GPIO_QMSI_0_NAME, &gpio_qmsi_init,
|
||||
DEVICE_PM_OPS_GET(gpio), &gpio_0_runtime, &gpio_0_config,
|
||||
SECONDARY, CONFIG_GPIO_QMSI_INIT_PRIORITY);
|
||||
DEVICE_DEFINE(gpio_0, CONFIG_GPIO_QMSI_0_NAME, &gpio_qmsi_init,
|
||||
gpio_qmsi_device_ctrl, &gpio_0_runtime, &gpio_0_config,
|
||||
SECONDARY, CONFIG_GPIO_QMSI_INIT_PRIORITY, NULL);
|
||||
|
||||
#endif /* CONFIG_GPIO_QMSI_0 */
|
||||
|
||||
|
@ -149,30 +191,44 @@ static struct gpio_qmsi_runtime gpio_aon_runtime;
|
|||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static uint32_t int_gpio_aon_mask_save;
|
||||
|
||||
static int gpio_aon_suspend_device(struct device *dev, int pm_policy)
|
||||
static int gpio_aon_suspend_device(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
int_gpio_aon_mask_save =
|
||||
REG_VAL(&QM_SCSS_INT->int_aon_gpio_mask);
|
||||
}
|
||||
int_gpio_aon_mask_save = REG_VAL(&QM_SCSS_INT->int_aon_gpio_mask);
|
||||
gpio_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_aon_resume_device(struct device *dev, int pm_policy)
|
||||
static int gpio_aon_resume_device_from_suspend(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
REG_VAL(&QM_SCSS_INT->int_aon_gpio_mask) =
|
||||
int_gpio_aon_mask_save;
|
||||
REG_VAL(&QM_SCSS_INT->int_aon_gpio_mask) = int_gpio_aon_mask_save;
|
||||
gpio_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int gpio_aon_device_ctrl(struct device *port, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return gpio_aon_suspend_device(port);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return gpio_aon_resume_device_from_suspend(port);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = gpio_qmsi_get_power_state(port);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(gpio_aon, gpio_aon_suspend_device, gpio_aon_resume_device);
|
||||
|
||||
DEVICE_INIT_PM(gpio_aon, CONFIG_GPIO_QMSI_AON_NAME, &gpio_qmsi_init,
|
||||
DEVICE_PM_OPS_GET(gpio_aon), &gpio_aon_runtime,
|
||||
&gpio_aon_config, SECONDARY, CONFIG_GPIO_QMSI_INIT_PRIORITY);
|
||||
DEVICE_DEFINE(gpio_aon, CONFIG_GPIO_QMSI_AON_NAME, &gpio_qmsi_init,
|
||||
gpio_aon_device_ctrl, &gpio_aon_runtime, &gpio_aon_config,
|
||||
SECONDARY, CONFIG_GPIO_QMSI_INIT_PRIORITY, NULL);
|
||||
|
||||
#endif /* CONFIG_GPIO_QMSI_AON */
|
||||
|
||||
|
@ -422,6 +478,8 @@ int gpio_qmsi_init(struct device *port)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
gpio_qmsi_set_power_state(port, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
port->driver_api = &api_funcs;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -66,95 +66,126 @@ struct i2c_qmsi_driver_data {
|
|||
struct nano_sem sem;
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
struct i2c_context_t ctx_save;
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static int i2c_suspend_device(struct device *dev, int pm_policy)
|
||||
|
||||
|
||||
static void i2c_qmsi_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct i2c_qmsi_driver_data *drv_data = dev->driver_data;
|
||||
|
||||
drv_data->device_power_state = power_state;
|
||||
}
|
||||
|
||||
static uint32_t i2c_qmsi_get_power_state(struct device *dev)
|
||||
{
|
||||
struct i2c_qmsi_driver_data *drv_data = dev->driver_data;
|
||||
|
||||
return drv_data->device_power_state;
|
||||
}
|
||||
|
||||
static int i2c_suspend_device(struct device *dev)
|
||||
{
|
||||
if (device_busy_check(dev)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
qm_i2c_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
qm_i2c_reg_t *const regs = QM_I2C[instance];
|
||||
struct i2c_qmsi_driver_data *drv_data = dev->driver_data;
|
||||
struct i2c_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
qm_i2c_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
qm_i2c_reg_t *const regs = QM_I2C[instance];
|
||||
struct i2c_qmsi_driver_data *drv_data = dev->driver_data;
|
||||
struct i2c_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
|
||||
ctx_save->ic_con = regs->ic_con;
|
||||
ctx_save->ic_fs_spklen = regs->ic_fs_spklen;
|
||||
ctx_save->ic_hs_spklen = regs->ic_hs_spklen;
|
||||
ctx_save->ic_ss_scl_lcnt = regs->ic_ss_scl_lcnt;
|
||||
ctx_save->ic_ss_scl_hcnt = regs->ic_ss_scl_hcnt;
|
||||
ctx_save->ic_fs_scl_lcnt = regs->ic_fs_scl_lcnt;
|
||||
ctx_save->ic_fs_scl_hcnt = regs->ic_fs_scl_hcnt;
|
||||
ctx_save->ic_hs_scl_lcnt = regs->ic_hs_scl_lcnt;
|
||||
ctx_save->ic_hs_scl_hcnt = regs->ic_hs_scl_hcnt;
|
||||
ctx_save->ic_intr_mask = regs->ic_intr_mask;
|
||||
ctx_save->ic_sda_hold = regs->ic_sda_hold;
|
||||
ctx_save->ic_sda_setup = regs->ic_sda_setup;
|
||||
ctx_save->ic_ack_general_call = regs->ic_ack_general_call;
|
||||
ctx_save->ic_sar = regs->ic_sar;
|
||||
ctx_save->ic_dma_cr = regs->ic_dma_cr;
|
||||
ctx_save->ic_dma_tdlr = regs->ic_dma_tdlr;
|
||||
ctx_save->ic_dma_rdlr = regs->ic_dma_rdlr;
|
||||
|
||||
if (instance == QM_I2C_0) {
|
||||
ctx_save->int_i2c_mst_mask =
|
||||
QM_SCSS_INT->int_i2c_mst_0_mask;
|
||||
} else {
|
||||
ctx_save->int_i2c_mst_mask =
|
||||
QM_SCSS_INT->int_i2c_mst_1_mask;
|
||||
}
|
||||
ctx_save->ic_con = regs->ic_con;
|
||||
ctx_save->ic_fs_spklen = regs->ic_fs_spklen;
|
||||
ctx_save->ic_hs_spklen = regs->ic_hs_spklen;
|
||||
ctx_save->ic_ss_scl_lcnt = regs->ic_ss_scl_lcnt;
|
||||
ctx_save->ic_ss_scl_hcnt = regs->ic_ss_scl_hcnt;
|
||||
ctx_save->ic_fs_scl_lcnt = regs->ic_fs_scl_lcnt;
|
||||
ctx_save->ic_fs_scl_hcnt = regs->ic_fs_scl_hcnt;
|
||||
ctx_save->ic_hs_scl_lcnt = regs->ic_hs_scl_lcnt;
|
||||
ctx_save->ic_hs_scl_hcnt = regs->ic_hs_scl_hcnt;
|
||||
ctx_save->ic_intr_mask = regs->ic_intr_mask;
|
||||
ctx_save->ic_sda_hold = regs->ic_sda_hold;
|
||||
ctx_save->ic_sda_setup = regs->ic_sda_setup;
|
||||
ctx_save->ic_ack_general_call = regs->ic_ack_general_call;
|
||||
ctx_save->ic_sar = regs->ic_sar;
|
||||
ctx_save->ic_dma_cr = regs->ic_dma_cr;
|
||||
ctx_save->ic_dma_tdlr = regs->ic_dma_tdlr;
|
||||
ctx_save->ic_dma_rdlr = regs->ic_dma_rdlr;
|
||||
|
||||
if (instance == QM_I2C_0) {
|
||||
ctx_save->int_i2c_mst_mask = QM_SCSS_INT->int_i2c_mst_0_mask;
|
||||
} else {
|
||||
ctx_save->int_i2c_mst_mask = QM_SCSS_INT->int_i2c_mst_1_mask;
|
||||
}
|
||||
|
||||
i2c_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_resume_device(struct device *dev, int pm_policy)
|
||||
static int i2c_resume_device_from_suspend(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
struct i2c_qmsi_config_info *config = dev->config->config_info;
|
||||
qm_i2c_reg_t *const regs = QM_I2C[config->instance];
|
||||
struct i2c_qmsi_driver_data *drv_data = dev->driver_data;
|
||||
struct i2c_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
struct i2c_qmsi_config_info *config = dev->config->config_info;
|
||||
qm_i2c_reg_t *const regs = QM_I2C[config->instance];
|
||||
struct i2c_qmsi_driver_data *drv_data = dev->driver_data;
|
||||
struct i2c_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
|
||||
regs->ic_con = ctx_save->ic_con;
|
||||
regs->ic_fs_spklen = ctx_save->ic_fs_spklen;
|
||||
regs->ic_hs_spklen = ctx_save->ic_hs_spklen;
|
||||
regs->ic_ss_scl_lcnt = ctx_save->ic_ss_scl_lcnt;
|
||||
regs->ic_ss_scl_hcnt = ctx_save->ic_ss_scl_hcnt;
|
||||
regs->ic_fs_scl_lcnt = ctx_save->ic_fs_scl_lcnt;
|
||||
regs->ic_fs_scl_hcnt = ctx_save->ic_fs_scl_hcnt;
|
||||
regs->ic_hs_scl_lcnt = ctx_save->ic_hs_scl_lcnt;
|
||||
regs->ic_hs_scl_hcnt = ctx_save->ic_hs_scl_hcnt;
|
||||
regs->ic_intr_mask = ctx_save->ic_intr_mask;
|
||||
regs->ic_sda_hold = ctx_save->ic_sda_hold;
|
||||
regs->ic_sda_setup = ctx_save->ic_sda_setup;
|
||||
regs->ic_ack_general_call = ctx_save->ic_ack_general_call;
|
||||
regs->ic_sar = ctx_save->ic_sar;
|
||||
regs->ic_dma_cr = ctx_save->ic_dma_cr;
|
||||
regs->ic_dma_tdlr = ctx_save->ic_dma_tdlr;
|
||||
regs->ic_dma_rdlr = ctx_save->ic_dma_rdlr;
|
||||
regs->ic_con = ctx_save->ic_con;
|
||||
regs->ic_fs_spklen = ctx_save->ic_fs_spklen;
|
||||
regs->ic_hs_spklen = ctx_save->ic_hs_spklen;
|
||||
regs->ic_ss_scl_lcnt = ctx_save->ic_ss_scl_lcnt;
|
||||
regs->ic_ss_scl_hcnt = ctx_save->ic_ss_scl_hcnt;
|
||||
regs->ic_fs_scl_lcnt = ctx_save->ic_fs_scl_lcnt;
|
||||
regs->ic_fs_scl_hcnt = ctx_save->ic_fs_scl_hcnt;
|
||||
regs->ic_hs_scl_lcnt = ctx_save->ic_hs_scl_lcnt;
|
||||
regs->ic_hs_scl_hcnt = ctx_save->ic_hs_scl_hcnt;
|
||||
regs->ic_intr_mask = ctx_save->ic_intr_mask;
|
||||
regs->ic_sda_hold = ctx_save->ic_sda_hold;
|
||||
regs->ic_sda_setup = ctx_save->ic_sda_setup;
|
||||
regs->ic_ack_general_call = ctx_save->ic_ack_general_call;
|
||||
regs->ic_sar = ctx_save->ic_sar;
|
||||
regs->ic_dma_cr = ctx_save->ic_dma_cr;
|
||||
regs->ic_dma_tdlr = ctx_save->ic_dma_tdlr;
|
||||
regs->ic_dma_rdlr = ctx_save->ic_dma_rdlr;
|
||||
|
||||
if (config->instance == QM_I2C_0) {
|
||||
QM_SCSS_INT->int_i2c_mst_0_mask =
|
||||
ctx_save->int_i2c_mst_mask;
|
||||
} else {
|
||||
QM_SCSS_INT->int_i2c_mst_1_mask =
|
||||
ctx_save->int_i2c_mst_mask;
|
||||
if (config->instance == QM_I2C_0) {
|
||||
QM_SCSS_INT->int_i2c_mst_0_mask = ctx_save->int_i2c_mst_mask;
|
||||
} else {
|
||||
QM_SCSS_INT->int_i2c_mst_1_mask = ctx_save->int_i2c_mst_mask;
|
||||
}
|
||||
|
||||
i2c_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int i2c_device_ctrl(struct device *dev, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return i2c_suspend_device(dev);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return i2c_resume_device_from_suspend(dev);
|
||||
}
|
||||
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = i2c_qmsi_get_power_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define i2c_qmsi_set_power_state(...)
|
||||
#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(i2c, i2c_suspend_device, i2c_resume_device);
|
||||
|
||||
#ifdef CONFIG_I2C_0
|
||||
|
||||
static struct i2c_qmsi_driver_data driver_data_0;
|
||||
|
@ -165,9 +196,9 @@ static struct i2c_qmsi_config_info config_info_0 = {
|
|||
.clock_gate = CLK_PERIPH_I2C_M0_REGISTER | CLK_PERIPH_CLK,
|
||||
};
|
||||
|
||||
DEVICE_INIT_PM(i2c_0, CONFIG_I2C_0_NAME, &i2c_qmsi_init,
|
||||
DEVICE_PM_OPS_GET(i2c), &driver_data_0, &config_info_0,
|
||||
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||
DEVICE_DEFINE(i2c_0, CONFIG_I2C_0_NAME, &i2c_qmsi_init,
|
||||
i2c_device_ctrl, &driver_data_0, &config_info_0, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL);
|
||||
|
||||
#endif /* CONFIG_I2C_0 */
|
||||
|
||||
|
@ -181,9 +212,9 @@ static struct i2c_qmsi_config_info config_info_1 = {
|
|||
.clock_gate = CLK_PERIPH_I2C_M1_REGISTER | CLK_PERIPH_CLK,
|
||||
};
|
||||
|
||||
DEVICE_INIT_PM(i2c_1, CONFIG_I2C_1_NAME, &i2c_qmsi_init,
|
||||
DEVICE_PM_OPS_GET(i2c), &driver_data_1, &config_info_1,
|
||||
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||
DEVICE_DEFINE(i2c_1, CONFIG_I2C_1_NAME, &i2c_qmsi_init,
|
||||
i2c_device_ctrl, &driver_data_1, &config_info_1, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL);
|
||||
|
||||
#endif /* CONFIG_I2C_1 */
|
||||
|
||||
|
@ -346,5 +377,8 @@ static int i2c_qmsi_init(struct device *dev)
|
|||
}
|
||||
|
||||
dev->driver_api = &api;
|
||||
|
||||
i2c_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
#include <power.h>
|
||||
uint32_t ioapic_suspend_buf[SUSPEND_BITS_REQD / 32] = {0};
|
||||
static uint32_t ioapic_device_power_state;
|
||||
#endif
|
||||
|
||||
static uint32_t __IoApicGet(int32_t offset);
|
||||
|
@ -139,6 +140,9 @@ int _ioapic_init(struct device *unused)
|
|||
ioApicRedSetHi(ix, 0);
|
||||
ioApicRedSetLo(ix, rteValue);
|
||||
}
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
ioapic_device_power_state = DEVICE_PM_ACTIVE_STATE;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -215,36 +219,29 @@ uint32_t restore_flags(unsigned int irq)
|
|||
}
|
||||
|
||||
|
||||
int ioapic_suspend(struct device *port, int pm_policy)
|
||||
int ioapic_suspend(struct device *port)
|
||||
{
|
||||
int irq;
|
||||
uint32_t rte_lo;
|
||||
|
||||
ARG_UNUSED(port);
|
||||
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
|
||||
memset(ioapic_suspend_buf, 0, (SUSPEND_BITS_REQD >> 3));
|
||||
|
||||
for (irq = 0; irq < CONFIG_IOAPIC_NUM_RTES; irq++) {
|
||||
|
||||
/*
|
||||
* The following check is to figure out the registered
|
||||
* IRQ lines, so as to limit ourselves to saving the
|
||||
* flags for them only.
|
||||
*/
|
||||
if (_irq_to_interrupt_vector[irq]) {
|
||||
|
||||
rte_lo = ioApicRedGetLo(irq);
|
||||
store_flags(irq, rte_lo);
|
||||
}
|
||||
memset(ioapic_suspend_buf, 0, (SUSPEND_BITS_REQD >> 3));
|
||||
for (irq = 0; irq < CONFIG_IOAPIC_NUM_RTES; irq++) {
|
||||
/*
|
||||
* The following check is to figure out the registered
|
||||
* IRQ lines, so as to limit ourselves to saving the
|
||||
* flags for them only.
|
||||
*/
|
||||
if (_irq_to_interrupt_vector[irq]) {
|
||||
rte_lo = ioApicRedGetLo(irq);
|
||||
store_flags(irq, rte_lo);
|
||||
}
|
||||
}
|
||||
|
||||
ioapic_device_power_state = DEVICE_PM_SUSPEND_STATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ioapic_resume(struct device *port, int pm_policy)
|
||||
int ioapic_resume_from_suspend(struct device *port)
|
||||
{
|
||||
int irq;
|
||||
uint32_t flags;
|
||||
|
@ -252,30 +249,45 @@ int ioapic_resume(struct device *port, int pm_policy)
|
|||
|
||||
ARG_UNUSED(port);
|
||||
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
for (irq = 0; irq < CONFIG_IOAPIC_NUM_RTES; irq++) {
|
||||
if (_irq_to_interrupt_vector[irq]) {
|
||||
/* Get the saved flags */
|
||||
flags = restore_flags(irq);
|
||||
/* Appending the flags that are never modified */
|
||||
flags = flags | IOAPIC_FIXED | IOAPIC_PHYSICAL;
|
||||
|
||||
for (irq = 0; irq < CONFIG_IOAPIC_NUM_RTES; irq++) {
|
||||
|
||||
if (_irq_to_interrupt_vector[irq]) {
|
||||
/* Get the saved flags */
|
||||
flags = restore_flags(irq);
|
||||
/* Appending the flags that are never modified */
|
||||
flags = flags | IOAPIC_FIXED | IOAPIC_PHYSICAL;
|
||||
|
||||
rteValue = (_irq_to_interrupt_vector[irq] &
|
||||
IOAPIC_VEC_MASK) | flags;
|
||||
} else {
|
||||
/* Initialize the other RTEs to sane values */
|
||||
rteValue = IOAPIC_EDGE | IOAPIC_HIGH |
|
||||
IOAPIC_FIXED | IOAPIC_INT_MASK |
|
||||
IOAPIC_PHYSICAL | 0 ; /* dummy vector*/
|
||||
}
|
||||
|
||||
ioApicRedSetHi(irq, 0);
|
||||
ioApicRedSetLo(irq, rteValue);
|
||||
rteValue = (_irq_to_interrupt_vector[irq] &
|
||||
IOAPIC_VEC_MASK) | flags;
|
||||
} else {
|
||||
/* Initialize the other RTEs to sane values */
|
||||
rteValue = IOAPIC_EDGE | IOAPIC_HIGH |
|
||||
IOAPIC_FIXED | IOAPIC_INT_MASK |
|
||||
IOAPIC_PHYSICAL | 0 ; /* dummy vector*/
|
||||
}
|
||||
ioApicRedSetHi(irq, 0);
|
||||
ioApicRedSetLo(irq, rteValue);
|
||||
}
|
||||
ioapic_device_power_state = DEVICE_PM_ACTIVE_STATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int ioapic_device_ctrl(struct device *device, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return ioapic_suspend(device);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return ioapic_resume_from_suspend(device);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = ioapic_device_power_state;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -441,12 +453,8 @@ static void _IoApicRedUpdateLo(unsigned int irq,
|
|||
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
struct device_pm_ops ioapic_pm_ops = {
|
||||
.suspend = ioapic_suspend,
|
||||
.resume = ioapic_resume
|
||||
};
|
||||
SYS_INIT_PM("ioapic", _ioapic_init, &ioapic_pm_ops, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
SYS_DEVICE_DEFINE("ioapic", _ioapic_init, ioapic_device_ctrl, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
#else
|
||||
SYS_INIT(_ioapic_init, PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
#endif
|
||||
|
|
|
@ -195,6 +195,7 @@
|
|||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
#include <power.h>
|
||||
uint32_t loapic_suspend_buf[LOPIC_SUSPEND_BITS_REQD / 32] = {0};
|
||||
static uint32_t loapic_device_power_state;
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -273,6 +274,9 @@ static int _loapic_init(struct device *unused)
|
|||
#else
|
||||
*(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_EOI) = 0;
|
||||
#endif
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
loapic_device_power_state = DEVICE_PM_ACTIVE_STATE;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -428,17 +432,13 @@ int __irq_controller_isr_vector_get(void)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static int loapic_suspend(struct device *port, int pm_policy)
|
||||
static int loapic_suspend(struct device *port)
|
||||
{
|
||||
volatile int *pLvt; /* pointer to local vector table */
|
||||
int loapic_irq;
|
||||
|
||||
ARG_UNUSED(port);
|
||||
|
||||
if (pm_policy != SYS_PM_DEEP_SLEEP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(loapic_suspend_buf, 0, (LOPIC_SUSPEND_BITS_REQD >> 3));
|
||||
|
||||
for (loapic_irq = 0; loapic_irq < LOAPIC_IRQ_COUNT; loapic_irq++) {
|
||||
|
@ -458,19 +458,16 @@ static int loapic_suspend(struct device *port, int pm_policy)
|
|||
}
|
||||
}
|
||||
}
|
||||
loapic_device_power_state = DEVICE_PM_SUSPEND_STATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int loapic_resume(struct device *port, int pm_policy)
|
||||
int loapic_resume(struct device *port)
|
||||
{
|
||||
int loapic_irq;
|
||||
|
||||
ARG_UNUSED(port);
|
||||
|
||||
if (pm_policy != SYS_PM_DEEP_SLEEP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assuming all loapic device registers lose their state, the call to
|
||||
* _loapic_init(), should bring all the registers to a sane state.
|
||||
*/
|
||||
|
@ -489,16 +486,34 @@ static int loapic_resume(struct device *port, int pm_policy)
|
|||
}
|
||||
}
|
||||
}
|
||||
loapic_device_power_state = DEVICE_PM_ACTIVE_STATE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct device_pm_ops loapic_pm_ops = {
|
||||
.suspend = loapic_suspend,
|
||||
.resume = loapic_resume
|
||||
};
|
||||
SYS_INIT_PM("loapic", _loapic_init, &loapic_pm_ops, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int loapic_device_ctrl(struct device *port, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return loapic_suspend(port);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return loapic_resume(port);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = loapic_device_power_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_DEVICE_DEFINE("loapic", _loapic_init, loapic_device_ctrl, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
#else
|
||||
SYS_INIT(_loapic_init, PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */
|
||||
|
|
|
@ -619,6 +619,38 @@ static int pwm_ftm_set_phase(struct device *dev, int access_op,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
/**
|
||||
* @brief API to set device power state
|
||||
*
|
||||
* This function simply sets the device power state in driver_data
|
||||
*
|
||||
* @param dev Device struct
|
||||
* @param power_state device power state to be saved
|
||||
* @return N/A
|
||||
*/
|
||||
static void pwm_ftm_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct pwm_ftm_drv_data *context = dev->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief API to get device power state
|
||||
*
|
||||
* This function simply returns the device power state
|
||||
* from driver_data
|
||||
*
|
||||
* @param dev Device struct
|
||||
* @return device power state
|
||||
*/
|
||||
static uint32_t pwm_ftm_get_power_state(struct device *dev)
|
||||
{
|
||||
struct pwm_ftm_drv_data *context = dev->driver_data;
|
||||
|
||||
return context->device_power_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief API call to disable FTM
|
||||
*
|
||||
|
@ -626,12 +658,10 @@ static int pwm_ftm_set_phase(struct device *dev, int access_op,
|
|||
* disabling the FTM
|
||||
*
|
||||
* @param dev Device struct
|
||||
* @param pm_policy The power management policy to enact on the device
|
||||
*
|
||||
* @return 0 if successful, failed otherwise
|
||||
*/
|
||||
|
||||
static int pwm_ftm_suspend(struct device *dev, int pm_policy)
|
||||
static int pwm_ftm_suspend(struct device *dev)
|
||||
{
|
||||
uint32_t reg_val;
|
||||
|
||||
|
@ -650,6 +680,7 @@ static int pwm_ftm_suspend(struct device *dev, int pm_policy)
|
|||
|
||||
sys_write32(reg_val, PWM_K64_FTM_SC(config->reg_base));
|
||||
|
||||
pwm_ftm_set_power_state(DEVICE_PM_SUSPEND_STATE);
|
||||
SYS_LOG_DBG("done.");
|
||||
|
||||
return 0;
|
||||
|
@ -664,13 +695,9 @@ static int pwm_ftm_suspend(struct device *dev, int pm_policy)
|
|||
* to "no clock selected" due to a call to pwm_ftm_suspend.
|
||||
*
|
||||
* @param dev Device struct
|
||||
* @param pm_policy The power management policy from which the device is
|
||||
* returning
|
||||
*
|
||||
* @return 0 if successful, failed otherwise
|
||||
*/
|
||||
|
||||
static int pwm_ftm_resume(struct device *dev, int pm_policy)
|
||||
static int pwm_ftm_resume_from_suspend(struct device *dev)
|
||||
{
|
||||
uint32_t clock_source;
|
||||
uint32_t reg_val;
|
||||
|
@ -693,13 +720,37 @@ static int pwm_ftm_resume(struct device *dev, int pm_policy)
|
|||
|
||||
sys_write32(reg_val, PWM_K64_FTM_SC(config->reg_base));
|
||||
|
||||
pwm_ftm_set_power_state(DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
SYS_LOG_DBG("done.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int pwm_ftm_device_ctrl(struct device *dev, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return pwm_ftm_suspend(dev);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return pwm_ftm_resume_from_suspend(dev);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = pwm_ftm_get_power_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define pwm_ftm_set_power_state(...)
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(pwm, pwm_ftm_suspend, pwm_ftm_resume);
|
||||
|
||||
static struct pwm_driver_api pwm_ftm_drv_api_funcs = {
|
||||
.config = pwm_ftm_configure,
|
||||
|
@ -718,7 +769,7 @@ int pwm_ftm_init(struct device *dev)
|
|||
{
|
||||
|
||||
SYS_LOG_DBG("...");
|
||||
|
||||
pwm_ftm_set_power_state(DEVICE_PM_ACTIVE_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -762,11 +813,10 @@ static struct pwm_ftm_config pwm_ftm_0_cfg = {
|
|||
|
||||
static struct pwm_ftm_drv_data pwm_ftm_0_drvdata;
|
||||
|
||||
DEVICE_AND_API_INIT_PM(pwm_ftm_0, CONFIG_PWM_K64_FTM_0_DEV_NAME, pwm_ftm_init,
|
||||
DEVICE_PM_OPS_GET(pwm), &pwm_ftm_0_drvdata,
|
||||
&pwm_ftm_0_cfg, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&pwm_ftm_drv_api_funcs);
|
||||
DEVICE_DEFINE(pwm_ftm_0, CONFIG_PWM_K64_FTM_0_DEV_NAME, pwm_ftm_init,
|
||||
pwm_ftm_device_ctrl, &pwm_ftm_0_drvdata, &pwm_ftm_0_cfg,
|
||||
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&pwm_ftm_drv_api_funcs);
|
||||
|
||||
#endif /* CONFIG_PWM_K64_FTM_0 */
|
||||
|
||||
|
@ -809,11 +859,10 @@ static struct pwm_ftm_config pwm_ftm_1_cfg = {
|
|||
|
||||
static struct pwm_ftm_drv_data pwm_ftm_1_drvdata;
|
||||
|
||||
DEVICE_AND_API_INIT_PM(pwm_ftm_1, CONFIG_PWM_K64_FTM_1_DEV_NAME, pwm_ftm_init,
|
||||
DEVICE_PM_OPS_GET(pwm), &pwm_ftm_1_drvdata,
|
||||
&pwm_ftm_1_cfg, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&pwm_ftm_drv_api_funcs);
|
||||
DEVICE_DEFINE(pwm_ftm_1, CONFIG_PWM_K64_FTM_1_DEV_NAME, pwm_ftm_init,
|
||||
pwm_ftm_device_ctrl, &pwm_ftm_1_drvdata, &pwm_ftm_1_cfg,
|
||||
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&pwm_ftm_drv_api_funcs);
|
||||
|
||||
#endif /* CONFIG_PWM_K64_FTM_1 */
|
||||
|
||||
|
@ -857,11 +906,10 @@ static struct pwm_ftm_config pwm_ftm_2_cfg = {
|
|||
|
||||
static struct pwm_ftm_drv_data pwm_ftm_2_drvdata;
|
||||
|
||||
DEVICE_AND_API_INIT_PM(pwm_ftm_2, CONFIG_PWM_K64_FTM_2_DEV_NAME, pwm_ftm_init,
|
||||
DEVICE_PM_OPS_GET(pwm), &pwm_ftm_2_drvdata,
|
||||
&pwm_ftm_2_cfg, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&pwm_ftm_drv_api_funcs);
|
||||
DEVICE_DEFINE(pwm_ftm_2, CONFIG_PWM_K64_FTM_2_DEV_NAME, pwm_ftm_init,
|
||||
pwm_ftm_device_ctrl, &pwm_ftm_2_drvdata, &pwm_ftm_2_cfg,
|
||||
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&pwm_ftm_drv_api_funcs);
|
||||
|
||||
#endif /* CONFIG_PWM_K64_FTM_2 */
|
||||
|
||||
|
@ -905,10 +953,9 @@ static struct pwm_ftm_config pwm_ftm_3_cfg = {
|
|||
|
||||
static struct pwm_ftm_drv_data pwm_ftm_3_drvdata;
|
||||
|
||||
DEVICE_AND_API_INIT_PM(pwm_ftm_3, CONFIG_PWM_K64_FTM_3_DEV_NAME, pwm_ftm_init,
|
||||
DEVICE_PM_OPS_GET(pwm), &pwm_ftm_3_drvdata,
|
||||
&pwm_ftm_3_cfg, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&pwm_ftm_drv_api_funcs);
|
||||
DEVICE_DEFINE(pwm_ftm_3, CONFIG_PWM_K64_FTM_3_DEV_NAME, pwm_ftm_init,
|
||||
pwm_ftm_device_ctrl, &pwm_ftm_3_drvdata, &pwm_ftm_3_cfg,
|
||||
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&pwm_ftm_drv_api_funcs);
|
||||
|
||||
#endif /* CONFIG_PWM_K64_FTM_3 */
|
||||
|
|
|
@ -180,6 +180,9 @@ struct pwm_ftm_config {
|
|||
/** Runtime driver data */
|
||||
struct pwm_ftm_drv_data {
|
||||
uint32_t phase[4];
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* __PWM_K64_FTM_H__ */
|
||||
|
|
|
@ -50,6 +50,9 @@
|
|||
|
||||
struct pwm_data {
|
||||
struct nano_sem sem;
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PWM_QMSI_API_REENTRANCY
|
||||
|
@ -344,6 +347,17 @@ static struct pwm_driver_api pwm_qmsi_drv_api_funcs = {
|
|||
.set_phase = pwm_qmsi_set_phase
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static void pwm_qmsi_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct pwm_data *context = dev->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
#else
|
||||
#define pwm_qmsi_set_power_state(...)
|
||||
#endif
|
||||
|
||||
static int pwm_qmsi_init(struct device *dev)
|
||||
{
|
||||
uint32_t *channel_period = dev->config->config_info;
|
||||
|
@ -357,6 +371,8 @@ static int pwm_qmsi_init(struct device *dev)
|
|||
|
||||
pwm_reentrancy_init(dev);
|
||||
|
||||
pwm_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -374,54 +390,75 @@ struct pwm_ctx {
|
|||
|
||||
static struct pwm_ctx pwm_ctx_save;
|
||||
|
||||
static int pwm_qmsi_suspend(struct device *dev, int pm_policy)
|
||||
static uint32_t pwm_qmsi_get_power_state(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
int i;
|
||||
struct pwm_data *context = dev->driver_data;
|
||||
|
||||
pwm_ctx_save.int_pwm_timer_mask =
|
||||
QM_SCSS_INT->int_pwm_timer_mask;
|
||||
for (i = 0; i < CONFIG_PWM_QMSI_NUM_PORTS; i++) {
|
||||
qm_pwm_channel_t *channel;
|
||||
struct pwm_channel_ctx *channel_save;
|
||||
return context->device_power_state;
|
||||
}
|
||||
|
||||
channel = &QM_PWM->timer[i];
|
||||
channel_save = &pwm_ctx_save.channels[i];
|
||||
channel_save->loadcount1 = channel->loadcount;
|
||||
channel_save->controlreg = channel->controlreg;
|
||||
channel_save->loadcount2 = QM_PWM->timer_loadcount2[i];
|
||||
}
|
||||
static int pwm_qmsi_suspend(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
pwm_ctx_save.int_pwm_timer_mask =
|
||||
QM_SCSS_INT->int_pwm_timer_mask;
|
||||
for (i = 0; i < CONFIG_PWM_QMSI_NUM_PORTS; i++) {
|
||||
qm_pwm_channel_t *channel;
|
||||
struct pwm_channel_ctx *channel_save;
|
||||
|
||||
channel = &QM_PWM->timer[i];
|
||||
channel_save = &pwm_ctx_save.channels[i];
|
||||
channel_save->loadcount1 = channel->loadcount;
|
||||
channel_save->controlreg = channel->controlreg;
|
||||
channel_save->loadcount2 = QM_PWM->timer_loadcount2[i];
|
||||
}
|
||||
|
||||
pwm_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwm_qmsi_resume(struct device *dev, int pm_policy)
|
||||
static int pwm_qmsi_resume_from_suspend(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_PWM_QMSI_NUM_PORTS; i++) {
|
||||
qm_pwm_channel_t *channel;
|
||||
struct pwm_channel_ctx *channel_save;
|
||||
for (i = 0; i < CONFIG_PWM_QMSI_NUM_PORTS; i++) {
|
||||
qm_pwm_channel_t *channel;
|
||||
struct pwm_channel_ctx *channel_save;
|
||||
|
||||
channel = &QM_PWM->timer[i];
|
||||
channel_save = &pwm_ctx_save.channels[i];
|
||||
channel->loadcount = channel_save->loadcount1;
|
||||
channel->controlreg = channel_save->controlreg;
|
||||
QM_PWM->timer_loadcount2[i] = channel_save->loadcount2;
|
||||
channel = &QM_PWM->timer[i];
|
||||
channel_save = &pwm_ctx_save.channels[i];
|
||||
channel->loadcount = channel_save->loadcount1;
|
||||
channel->controlreg = channel_save->controlreg;
|
||||
QM_PWM->timer_loadcount2[i] = channel_save->loadcount2;
|
||||
}
|
||||
QM_SCSS_INT->int_pwm_timer_mask = pwm_ctx_save.int_pwm_timer_mask;
|
||||
pwm_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int pwm_qmsi_device_ctrl(struct device *dev, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return pwm_qmsi_suspend(dev);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return pwm_qmsi_resume_from_suspend(dev);
|
||||
}
|
||||
QM_SCSS_INT->int_pwm_timer_mask =
|
||||
pwm_ctx_save.int_pwm_timer_mask;
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = pwm_qmsi_get_power_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(pwm, pwm_qmsi_suspend, pwm_qmsi_resume);
|
||||
|
||||
DEVICE_AND_API_INIT_PM(pwm_qmsi_0, CONFIG_PWM_QMSI_DEV_NAME, pwm_qmsi_init,
|
||||
DEVICE_PM_OPS_GET(pwm), PWM_CONTEXT, pwm_channel_period,
|
||||
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
(void *)&pwm_qmsi_drv_api_funcs);
|
||||
DEVICE_DEFINE(pwm_qmsi_0, CONFIG_PWM_QMSI_DEV_NAME, pwm_qmsi_init,
|
||||
pwm_qmsi_device_ctrl, PWM_CONTEXT, pwm_channel_period,
|
||||
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
(void *)&pwm_qmsi_drv_api_funcs);
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
struct rtc_data {
|
||||
struct nano_sem sem;
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RTC_QMSI_API_REENTRANCY
|
||||
|
@ -39,6 +42,25 @@ static const int reentrancy_protection = 1;
|
|||
static const int reentrancy_protection;
|
||||
#endif /* CONFIG_RTC_QMSI_API_REENTRANCY */
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
|
||||
static void rtc_qmsi_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct rtc_data *context = dev->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
|
||||
static uint32_t rtc_qmsi_get_power_state(struct device *dev)
|
||||
{
|
||||
struct rtc_data *context = dev->driver_data;
|
||||
|
||||
return context->device_power_state;
|
||||
}
|
||||
#else
|
||||
#define rtc_qmsi_set_power_state(...)
|
||||
#endif
|
||||
|
||||
static void rtc_reentrancy_init(struct device *dev)
|
||||
{
|
||||
struct rtc_data *context = dev->driver_data;
|
||||
|
@ -141,33 +163,50 @@ static int rtc_qmsi_init(struct device *dev)
|
|||
/* Route RTC interrupt to Lakemont */
|
||||
QM_SCSS_INT->int_rtc_mask &= ~BIT(0);
|
||||
|
||||
rtc_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static uint32_t int_rtc_mask_save;
|
||||
|
||||
static int rtc_suspend_device(struct device *dev, int pm_policy)
|
||||
static int rtc_suspend_device(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
int_rtc_mask_save = QM_SCSS_INT->int_rtc_mask;
|
||||
}
|
||||
|
||||
int_rtc_mask_save = QM_SCSS_INT->int_rtc_mask;
|
||||
rtc_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtc_resume_device(struct device *dev, int pm_policy)
|
||||
static int rtc_resume_device(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
QM_SCSS_INT->int_rtc_mask = int_rtc_mask_save;
|
||||
QM_SCSS_INT->int_rtc_mask = int_rtc_mask_save;
|
||||
rtc_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int rtc_qmsi_device_ctrl(struct device *dev, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return rtc_suspend_device(dev);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return rtc_resume_device(dev);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = rtc_qmsi_get_power_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(rtc, rtc_suspend_device, rtc_resume_device);
|
||||
|
||||
DEVICE_AND_API_INIT_PM(rtc, CONFIG_RTC_0_NAME, &rtc_qmsi_init,
|
||||
DEVICE_PM_OPS_GET(rtc), RTC_CONTEXT, NULL, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, (void *)&api);
|
||||
DEVICE_DEFINE(rtc, CONFIG_RTC_0_NAME, &rtc_qmsi_init, rtc_qmsi_device_ctrl,
|
||||
RTC_CONTEXT, NULL, SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
(void *)&api);
|
||||
|
|
|
@ -74,6 +74,8 @@ struct uart_qmsi_drv_data {
|
|||
uart_irq_callback_t user_cb;
|
||||
uint8_t iir_cache;
|
||||
};
|
||||
|
||||
#define uart_qmsi_set_power_state(...)
|
||||
#else
|
||||
struct uart_context_t {
|
||||
uint32_t ier; /**< Interrupt Enable Register. */
|
||||
|
@ -91,89 +93,123 @@ struct uart_qmsi_drv_data {
|
|||
uart_irq_callback_t user_cb;
|
||||
uint8_t iir_cache;
|
||||
struct uart_context_t ctx_save;
|
||||
uint32_t device_power_state;
|
||||
};
|
||||
|
||||
static int uart_suspend_device(struct device *dev, int pm_policy)
|
||||
static void uart_qmsi_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct uart_qmsi_drv_data *context = dev->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
|
||||
static uint32_t uart_qmsi_get_power_state(struct device *dev)
|
||||
{
|
||||
struct uart_qmsi_drv_data *context = dev->driver_data;
|
||||
|
||||
return context->device_power_state;
|
||||
}
|
||||
|
||||
static int uart_suspend_device(struct device *dev)
|
||||
{
|
||||
if (device_busy_check(dev)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
struct uart_qmsi_config_info *config = dev->config->config_info;
|
||||
qm_uart_reg_t *const regs = QM_UART[config->instance];
|
||||
struct uart_qmsi_drv_data *drv_data = dev->driver_data;
|
||||
struct uart_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
struct uart_qmsi_config_info *config = dev->config->config_info;
|
||||
qm_uart_reg_t *const regs = QM_UART[config->instance];
|
||||
struct uart_qmsi_drv_data *drv_data = dev->driver_data;
|
||||
struct uart_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
|
||||
if (config->instance == QM_UART_0) {
|
||||
ctx_save->int_uart_mask = QM_SCSS_INT->int_uart_0_mask;
|
||||
} else {
|
||||
ctx_save->int_uart_mask = QM_SCSS_INT->int_uart_1_mask;
|
||||
}
|
||||
|
||||
ctx_save->ier = regs->ier_dlh;
|
||||
ctx_save->lcr = regs->lcr;
|
||||
ctx_save->mcr = regs->mcr;
|
||||
ctx_save->scr = regs->scr;
|
||||
ctx_save->htx = regs->htx;
|
||||
ctx_save->dlf = regs->dlf;
|
||||
|
||||
/* When DLAB is set, DLL and DLH registers can be accessed. */
|
||||
regs->lcr |= QM_UART_LCR_DLAB;
|
||||
ctx_save->dlh = regs->ier_dlh;
|
||||
ctx_save->dll = regs->rbr_thr_dll;
|
||||
regs->lcr &= ~QM_UART_LCR_DLAB;
|
||||
if (config->instance == QM_UART_0) {
|
||||
ctx_save->int_uart_mask = QM_SCSS_INT->int_uart_0_mask;
|
||||
} else {
|
||||
ctx_save->int_uart_mask = QM_SCSS_INT->int_uart_1_mask;
|
||||
}
|
||||
|
||||
ctx_save->ier = regs->ier_dlh;
|
||||
ctx_save->lcr = regs->lcr;
|
||||
ctx_save->mcr = regs->mcr;
|
||||
ctx_save->scr = regs->scr;
|
||||
ctx_save->htx = regs->htx;
|
||||
ctx_save->dlf = regs->dlf;
|
||||
|
||||
/* When DLAB is set, DLL and DLH registers can be accessed. */
|
||||
regs->lcr |= QM_UART_LCR_DLAB;
|
||||
ctx_save->dlh = regs->ier_dlh;
|
||||
ctx_save->dll = regs->rbr_thr_dll;
|
||||
regs->lcr &= ~QM_UART_LCR_DLAB;
|
||||
|
||||
uart_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uart_resume_device(struct device *dev, int pm_policy)
|
||||
static int uart_resume_device_from_suspend(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
struct uart_qmsi_config_info *config = dev->config->config_info;
|
||||
qm_uart_reg_t *const regs = QM_UART[config->instance];
|
||||
struct uart_qmsi_drv_data *drv_data = dev->driver_data;
|
||||
struct uart_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
struct uart_qmsi_config_info *config = dev->config->config_info;
|
||||
qm_uart_reg_t *const regs = QM_UART[config->instance];
|
||||
struct uart_qmsi_drv_data *drv_data = dev->driver_data;
|
||||
struct uart_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
|
||||
clk_periph_enable(config->clock_gate);
|
||||
clk_periph_enable(config->clock_gate);
|
||||
|
||||
if (config->instance == QM_UART_0) {
|
||||
QM_SCSS_INT->int_uart_0_mask = ctx_save->int_uart_mask;
|
||||
} else {
|
||||
QM_SCSS_INT->int_uart_1_mask = ctx_save->int_uart_mask;
|
||||
if (config->instance == QM_UART_0) {
|
||||
QM_SCSS_INT->int_uart_0_mask = ctx_save->int_uart_mask;
|
||||
} else {
|
||||
QM_SCSS_INT->int_uart_1_mask = ctx_save->int_uart_mask;
|
||||
}
|
||||
|
||||
/* When DLAB is set, DLL and DLH registers can be accessed. */
|
||||
regs->lcr |= QM_UART_LCR_DLAB;
|
||||
regs->ier_dlh = ctx_save->dlh;
|
||||
regs->rbr_thr_dll = ctx_save->dll;
|
||||
regs->lcr &= ~QM_UART_LCR_DLAB;
|
||||
|
||||
regs->ier_dlh = ctx_save->ier;
|
||||
regs->lcr = ctx_save->lcr;
|
||||
regs->mcr = ctx_save->mcr;
|
||||
regs->scr = ctx_save->scr;
|
||||
regs->htx = ctx_save->htx;
|
||||
regs->dlf = ctx_save->dlf;
|
||||
|
||||
/*
|
||||
* FIFO control register cannot be read back,
|
||||
* default config is applied for this register.
|
||||
* Application will need to restore its own parameters.
|
||||
*/
|
||||
regs->iir_fcr =
|
||||
(QM_UART_FCR_FIFOE | QM_UART_FCR_RFIFOR |
|
||||
QM_UART_FCR_XFIFOR |
|
||||
QM_UART_FCR_DEFAULT_TX_RX_THRESHOLD);
|
||||
|
||||
uart_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int uart_qmsi_device_ctrl(struct device *dev, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return uart_suspend_device(dev);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return uart_resume_device_from_suspend(dev);
|
||||
}
|
||||
|
||||
/* When DLAB is set, DLL and DLH registers can be accessed. */
|
||||
regs->lcr |= QM_UART_LCR_DLAB;
|
||||
regs->ier_dlh = ctx_save->dlh;
|
||||
regs->rbr_thr_dll = ctx_save->dll;
|
||||
regs->lcr &= ~QM_UART_LCR_DLAB;
|
||||
|
||||
regs->ier_dlh = ctx_save->ier;
|
||||
regs->lcr = ctx_save->lcr;
|
||||
regs->mcr = ctx_save->mcr;
|
||||
regs->scr = ctx_save->scr;
|
||||
regs->htx = ctx_save->htx;
|
||||
regs->dlf = ctx_save->dlf;
|
||||
|
||||
/*
|
||||
* FIFO control register cannot be read back,
|
||||
* default config is applied for this register.
|
||||
* Application will need to restore its own parameters.
|
||||
*/
|
||||
regs->iir_fcr =
|
||||
(QM_UART_FCR_FIFOE | QM_UART_FCR_RFIFOR |
|
||||
QM_UART_FCR_XFIFOR |
|
||||
QM_UART_FCR_DEFAULT_TX_RX_THRESHOLD);
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = uart_qmsi_get_power_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(uart, uart_suspend_device, uart_resume_device);
|
||||
|
||||
#ifdef CONFIG_UART_QMSI_0
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
static void irq_config_func_0(struct device *dev);
|
||||
|
@ -197,9 +233,9 @@ static struct uart_qmsi_config_info config_info_0 = {
|
|||
|
||||
static struct uart_qmsi_drv_data drv_data_0;
|
||||
|
||||
DEVICE_INIT_PM(uart_0, CONFIG_UART_QMSI_0_NAME, &uart_qmsi_init,
|
||||
DEVICE_PM_OPS_GET(uart), &drv_data_0, &config_info_0, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||
DEVICE_DEFINE(uart_0, CONFIG_UART_QMSI_0_NAME, &uart_qmsi_init,
|
||||
uart_qmsi_device_ctrl, &drv_data_0, &config_info_0, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL);
|
||||
#endif /* CONFIG_UART_QMSI_0 */
|
||||
|
||||
#ifdef CONFIG_UART_QMSI_1
|
||||
|
@ -225,9 +261,9 @@ static struct uart_qmsi_config_info config_info_1 = {
|
|||
|
||||
static struct uart_qmsi_drv_data drv_data_1;
|
||||
|
||||
DEVICE_INIT_PM(uart_1, CONFIG_UART_QMSI_1_NAME, &uart_qmsi_init,
|
||||
DEVICE_PM_OPS_GET(uart), &drv_data_1, &config_info_1, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||
DEVICE_DEFINE(uart_1, CONFIG_UART_QMSI_1_NAME, &uart_qmsi_init,
|
||||
uart_qmsi_device_ctrl, &drv_data_1, &config_info_1, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL);
|
||||
#endif /* CONFIG_UART_QMSI_1 */
|
||||
|
||||
static int uart_qmsi_poll_in(struct device *dev, unsigned char *data)
|
||||
|
@ -518,6 +554,7 @@ static int uart_qmsi_init(struct device *dev)
|
|||
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
|
||||
dev->driver_api = &api;
|
||||
uart_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -365,6 +365,17 @@ static inline int spi_intel_setup(struct device *dev)
|
|||
#else
|
||||
#define spi_intel_setup(_unused_) (1)
|
||||
#endif /* CONFIG_PCI */
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
|
||||
static void spi_intel_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct spi_intel_data *context = dev->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
#else
|
||||
#define spi_intel_set_power_state(...)
|
||||
#endif
|
||||
|
||||
int spi_intel_init(struct device *dev)
|
||||
{
|
||||
|
@ -381,6 +392,8 @@ int spi_intel_init(struct device *dev)
|
|||
|
||||
device_sync_call_init(&spi->sync);
|
||||
|
||||
spi_intel_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
irq_enable(info->irq);
|
||||
|
||||
SYS_LOG_DBG("SPI Intel Driver initialized on device: %p", dev);
|
||||
|
@ -391,7 +404,15 @@ int spi_intel_init(struct device *dev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static int spi_intel_suspend(struct device *dev, int pm_policy)
|
||||
|
||||
static uint32_t spi_intel_get_power_state(struct device *dev)
|
||||
{
|
||||
struct spi_intel_data *context = dev->driver_data;
|
||||
|
||||
return context->device_power_state;
|
||||
}
|
||||
|
||||
static int spi_intel_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_intel_config *info = dev->config->config_info;
|
||||
|
||||
|
@ -400,10 +421,12 @@ static int spi_intel_suspend(struct device *dev, int pm_policy)
|
|||
clear_bit_sscr0_sse(info->regs);
|
||||
irq_disable(info->irq);
|
||||
|
||||
spi_intel_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spi_intel_resume(struct device *dev, int pm_policy)
|
||||
static int spi_intel_resume_from_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_intel_config *info = dev->config->config_info;
|
||||
|
||||
|
@ -412,11 +435,34 @@ static int spi_intel_resume(struct device *dev, int pm_policy)
|
|||
set_bit_sscr0_sse(info->regs);
|
||||
irq_enable(info->irq);
|
||||
|
||||
spi_intel_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(spi, spi_intel_suspend, spi_intel_resume);
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int spi_intel_device_ctrl(struct device *dev, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return spi_intel_suspend(dev);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return spi_intel_resume_from_suspend(dev);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = spi_intel_get_power_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define spi_intel_set_power_state(...)
|
||||
#endif
|
||||
|
||||
/* system bindings */
|
||||
#ifdef CONFIG_SPI_0
|
||||
|
@ -444,9 +490,9 @@ struct spi_intel_config spi_intel_config_0 = {
|
|||
};
|
||||
|
||||
/* SPI may use GPIO pin for CS, thus it needs to be initialized after GPIO */
|
||||
DEVICE_INIT_PM(spi_intel_port_0, CONFIG_SPI_0_NAME, spi_intel_init,
|
||||
DEVICE_PM_OPS_GET(spi), &spi_intel_data_port_0,
|
||||
&spi_intel_config_0, SECONDARY, CONFIG_SPI_INIT_PRIORITY);
|
||||
DEVICE_DEFINE(spi_intel_port_0, CONFIG_SPI_0_NAME, spi_intel_init,
|
||||
spi_intel_device_ctrl, &spi_intel_data_port_0,
|
||||
&spi_intel_config_0, SECONDARY, CONFIG_SPI_INIT_PRIORITY, NULL);
|
||||
|
||||
void spi_config_0_irq(void)
|
||||
{
|
||||
|
@ -481,9 +527,9 @@ struct spi_intel_config spi_intel_config_1 = {
|
|||
};
|
||||
|
||||
/* SPI may use GPIO pin for CS, thus it needs to be initialized after GPIO */
|
||||
DEVICE_INIT_PM(spi_intel_port_1, CONFIG_SPI_1_NAME, spi_intel_init,
|
||||
DEVICE_PM_OPS_GET(spi), &spi_intel_data_port_1,
|
||||
&spi_intel_config_1, SECONDARY, CONFIG_SPI_INIT_PRIORITY);
|
||||
DEVICE_DEFINE(spi_intel_port_1, CONFIG_SPI_1_NAME, spi_intel_init,
|
||||
spi_intel_device_ctrl, &spi_intel_data_port_1,
|
||||
&spi_intel_config_1, SECONDARY, CONFIG_SPI_INIT_PRIORITY, NULL);
|
||||
|
||||
void spi_config_1_irq(void)
|
||||
{
|
||||
|
|
|
@ -58,6 +58,9 @@ struct spi_intel_data {
|
|||
uint32_t transmitted;
|
||||
uint32_t received;
|
||||
uint32_t trans_len;
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Registers */
|
||||
|
|
|
@ -900,6 +900,25 @@ static struct spi_driver_api k64_spi_api = {
|
|||
.transceive = spi_k64_transceive,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
/**
|
||||
* @brief API to set device power state
|
||||
*
|
||||
* This function simply sets the device power state in driver_data
|
||||
*
|
||||
* @param dev Device struct
|
||||
* @param power_state device power state to be saved
|
||||
* @return N/A
|
||||
*/
|
||||
static void spi_k64_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct spi_k64_data *context = dev->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
#else
|
||||
#define spi_k64_set_power_state(...)
|
||||
#endif
|
||||
|
||||
int spi_k64_init(struct device *dev)
|
||||
{
|
||||
|
@ -959,6 +978,8 @@ int spi_k64_init(struct device *dev)
|
|||
|
||||
info->config_func();
|
||||
|
||||
spi_k64_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
irq_enable(info->irq);
|
||||
|
||||
/*
|
||||
|
@ -977,13 +998,27 @@ int spi_k64_init(struct device *dev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
/**
|
||||
* @brief API to get device power state
|
||||
*
|
||||
* This function simply returns the device power state
|
||||
* from driver_data
|
||||
*
|
||||
* @param dev Device struct
|
||||
* @return device power state
|
||||
*/
|
||||
static uint32_t spi_k64_get_power_state(struct device *dev)
|
||||
{
|
||||
struct spi_k64_data *context = dev->driver_data;
|
||||
|
||||
return context->device_power_state;
|
||||
}
|
||||
/**
|
||||
* @brief Suspend SPI host controller operations.
|
||||
* @param dev Pointer to the device structure for the driver instance
|
||||
* @param pm_policy The power management policy to enact on the device
|
||||
* @return 0 if successful, a negative errno value otherwise.
|
||||
*/
|
||||
static int spi_k64_suspend(struct device *dev, int pm_policy)
|
||||
static int spi_k64_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_k64_config *info = dev->config->config_info;
|
||||
|
||||
|
@ -996,6 +1031,8 @@ static int spi_k64_suspend(struct device *dev, int pm_policy)
|
|||
|
||||
sys_set_bit((info->regs + SPI_K64_REG_MCR), SPI_K64_MCR_MDIS_BIT);
|
||||
|
||||
spi_k64_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
|
||||
irq_disable(info->irq);
|
||||
|
||||
return 0;
|
||||
|
@ -1004,11 +1041,9 @@ static int spi_k64_suspend(struct device *dev, int pm_policy)
|
|||
/**
|
||||
* @brief Resume SPI host controller operations.
|
||||
* @param dev Pointer to the device structure for the driver instance
|
||||
* @param pm_policy The power management policy from which the device is
|
||||
* returning
|
||||
* @return 0 if successful, a negative errno value otherwise.
|
||||
*/
|
||||
static int spi_k64_resume(struct device *dev, int pm_policy)
|
||||
static int spi_k64_resume_from_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_k64_config *info = dev->config->config_info;
|
||||
|
||||
|
@ -1018,13 +1053,36 @@ static int spi_k64_resume(struct device *dev, int pm_policy)
|
|||
|
||||
sys_clear_bit((info->regs + SPI_K64_REG_MCR), SPI_K64_MCR_MDIS_BIT);
|
||||
|
||||
spi_k64_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
irq_enable(info->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(spi, spi_k64_suspend, spi_k64_resume);
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int spi_k64_device_ctrl(struct device *dev, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return spi_k64_suspend(dev);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return spi_k64_resume_from_suspend(dev);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = spi_k64_get_power_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define spi_k64_set_power_state(...)
|
||||
#endif
|
||||
|
||||
/* system bindings */
|
||||
#ifdef CONFIG_SPI_K64_0
|
||||
|
@ -1041,10 +1099,10 @@ struct spi_k64_config spi_k64_config_0 = {
|
|||
.config_func = spi_config_0_irq
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT_PM(spi_k64_port_0, CONFIG_SPI_K64_0_DEV_NAME, spi_k64_init,
|
||||
DEVICE_PM_OPS_GET(spi), &spi_k64_data_port_0,
|
||||
&spi_k64_config_0, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &k64_spi_api);
|
||||
DEVICE_DEFINE(spi_k64_port_0, CONFIG_SPI_K64_0_DEV_NAME, spi_k64_init,
|
||||
spi_k64_device_ctrl, &spi_k64_data_port_0,
|
||||
&spi_k64_config_0, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &k64_spi_api);
|
||||
|
||||
|
||||
void spi_config_0_irq(void)
|
||||
|
@ -1070,10 +1128,10 @@ struct spi_k64_config spi_k64_config_1 = {
|
|||
.config_func = spi_config_1_irq
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT_PM(spi_k64_port_1, CONFIG_SPI_K64_1_DEV_NAME, spi_k64_init,
|
||||
DEVICE_PM_OPS_GET(spi), &spi_k64_data_port_1,
|
||||
&spi_k64_config_1, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &k64_spi_api);
|
||||
DEVICE_DEFINE(spi_k64_port_1, CONFIG_SPI_K64_1_DEV_NAME, spi_k64_init,
|
||||
spi_k64_device_ctrl, &spi_k64_data_port_1,
|
||||
&spi_k64_config_1, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &k64_spi_api);
|
||||
|
||||
|
||||
void spi_config_1_irq(void)
|
||||
|
@ -1099,10 +1157,10 @@ struct spi_k64_config spi_k64_config_2 = {
|
|||
.config_func = spi_config_2_irq
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT_PM(spi_k64_port_2, CONFIG_SPI_K64_2_DEV_NAME, spi_k64_init,
|
||||
DEVICE_PM_OPS_GET(spi), &spi_k64_data_port_2,
|
||||
&spi_k64_config_2, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &k64_spi_api);
|
||||
DEVICE_DEFINE(spi_k64_port_2, CONFIG_SPI_K64_2_DEV_NAME, spi_k64_init,
|
||||
spi_k64_device_ctrl, &spi_k64_data_port_2,
|
||||
&spi_k64_config_2, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &k64_spi_api);
|
||||
|
||||
|
||||
void spi_config_2_irq(void)
|
||||
|
|
|
@ -40,6 +40,9 @@ struct spi_k64_data {
|
|||
uint32_t xfer_len;
|
||||
device_sync_call_t sync_info; /* sync call information */
|
||||
uint8_t error; /* error condition */
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Data transfer signal timing delays */
|
||||
|
|
|
@ -61,6 +61,7 @@ struct spi_qmsi_runtime {
|
|||
struct nano_sem sem;
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
struct spi_context_t ctx_save;
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -242,6 +243,23 @@ static struct device *gpio_cs_init(struct spi_qmsi_config *config)
|
|||
|
||||
return gpio;
|
||||
}
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static void spi_master_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct spi_qmsi_runtime *context = dev->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
|
||||
static uint32_t spi_master_get_power_state(struct device *dev)
|
||||
{
|
||||
struct spi_qmsi_runtime *context = dev->driver_data;
|
||||
|
||||
return context->device_power_state;
|
||||
}
|
||||
#else
|
||||
#define spi_master_set_power_state(...)
|
||||
#endif
|
||||
|
||||
static int spi_qmsi_init(struct device *dev)
|
||||
{
|
||||
|
@ -279,66 +297,79 @@ static int spi_qmsi_init(struct device *dev)
|
|||
nano_sem_init(&context->sem);
|
||||
nano_sem_give(&context->sem);
|
||||
|
||||
dev->driver_api = &spi_qmsi_api;
|
||||
spi_master_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
dev->driver_api = &spi_qmsi_api;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static int spi_master_suspend_device(struct device *dev, int pm_policy)
|
||||
static int spi_master_suspend_device(struct device *dev)
|
||||
{
|
||||
if (device_busy_check(dev)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
struct spi_qmsi_config *config = dev->config->config_info;
|
||||
qm_spi_reg_t *const regs = QM_SPI[config->spi];
|
||||
struct spi_qmsi_runtime *drv_data = dev->driver_data;
|
||||
struct spi_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
struct spi_qmsi_config *config = dev->config->config_info;
|
||||
qm_spi_reg_t *const regs = QM_SPI[config->spi];
|
||||
struct spi_qmsi_runtime *drv_data = dev->driver_data;
|
||||
struct spi_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
|
||||
if (config->spi == QM_SPI_MST_0) {
|
||||
ctx_save->int_spi_mask =
|
||||
QM_SCSS_INT->int_spi_mst_0_mask;
|
||||
} else {
|
||||
ctx_save->int_spi_mask =
|
||||
QM_SCSS_INT->int_spi_mst_1_mask;
|
||||
}
|
||||
|
||||
ctx_save->ctrlr0 = regs->ctrlr0;
|
||||
ctx_save->ser = regs->ser;
|
||||
ctx_save->baudr = regs->baudr;
|
||||
if (config->spi == QM_SPI_MST_0) {
|
||||
ctx_save->int_spi_mask = QM_SCSS_INT->int_spi_mst_0_mask;
|
||||
} else {
|
||||
ctx_save->int_spi_mask = QM_SCSS_INT->int_spi_mst_1_mask;
|
||||
}
|
||||
|
||||
ctx_save->ctrlr0 = regs->ctrlr0;
|
||||
ctx_save->ser = regs->ser;
|
||||
ctx_save->baudr = regs->baudr;
|
||||
|
||||
spi_master_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spi_master_resume_device(struct device *dev, int pm_policy)
|
||||
static int spi_master_resume_device_from_suspend(struct device *dev)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
struct spi_qmsi_config *config = dev->config->config_info;
|
||||
qm_spi_reg_t *const regs = QM_SPI[config->spi];
|
||||
struct spi_qmsi_runtime *drv_data = dev->driver_data;
|
||||
struct spi_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
struct spi_qmsi_config *config = dev->config->config_info;
|
||||
qm_spi_reg_t *const regs = QM_SPI[config->spi];
|
||||
struct spi_qmsi_runtime *drv_data = dev->driver_data;
|
||||
struct spi_context_t *const ctx_save = &drv_data->ctx_save;
|
||||
|
||||
if (config->spi == QM_SPI_MST_0) {
|
||||
QM_SCSS_INT->int_spi_mst_0_mask =
|
||||
ctx_save->int_spi_mask;
|
||||
} else {
|
||||
QM_SCSS_INT->int_spi_mst_1_mask =
|
||||
ctx_save->int_spi_mask;
|
||||
if (config->spi == QM_SPI_MST_0) {
|
||||
QM_SCSS_INT->int_spi_mst_0_mask = ctx_save->int_spi_mask;
|
||||
} else {
|
||||
QM_SCSS_INT->int_spi_mst_1_mask = ctx_save->int_spi_mask;
|
||||
}
|
||||
regs->ctrlr0 = ctx_save->ctrlr0;
|
||||
regs->ser = ctx_save->ser;
|
||||
regs->baudr = ctx_save->baudr;
|
||||
|
||||
spi_master_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int spi_master_qmsi_device_ctrl(struct device *port,
|
||||
uint32_t ctrl_command, void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return spi_master_suspend_device(port);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return spi_master_resume_device_from_suspend(port);
|
||||
}
|
||||
|
||||
regs->ctrlr0 = ctx_save->ctrlr0;
|
||||
regs->ser = ctx_save->ser;
|
||||
regs->baudr = ctx_save->baudr;
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = spi_master_get_power_state(port);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(spi_master, spi_master_suspend_device,
|
||||
spi_master_resume_device);
|
||||
|
||||
#ifdef CONFIG_SPI_0
|
||||
static struct spi_qmsi_config spi_qmsi_mst_0_config = {
|
||||
.spi = QM_SPI_MST_0,
|
||||
|
@ -350,9 +381,10 @@ static struct spi_qmsi_config spi_qmsi_mst_0_config = {
|
|||
|
||||
static struct spi_qmsi_runtime spi_qmsi_mst_0_runtime;
|
||||
|
||||
DEVICE_INIT_PM(spi_master_0, CONFIG_SPI_0_NAME, spi_qmsi_init,
|
||||
DEVICE_PM_OPS_GET(spi_master), &spi_qmsi_mst_0_runtime,
|
||||
&spi_qmsi_mst_0_config, SECONDARY, CONFIG_SPI_INIT_PRIORITY);
|
||||
DEVICE_DEFINE(spi_master_0, CONFIG_SPI_0_NAME, spi_qmsi_init,
|
||||
spi_master_qmsi_device_ctrl, &spi_qmsi_mst_0_runtime,
|
||||
&spi_qmsi_mst_0_config, SECONDARY, CONFIG_SPI_INIT_PRIORITY,
|
||||
NULL);
|
||||
#endif /* CONFIG_SPI_0 */
|
||||
|
||||
#ifdef CONFIG_SPI_1
|
||||
|
@ -366,7 +398,8 @@ static struct spi_qmsi_config spi_qmsi_mst_1_config = {
|
|||
|
||||
static struct spi_qmsi_runtime spi_qmsi_mst_1_runtime;
|
||||
|
||||
DEVICE_INIT_PM(spi_master_1, CONFIG_SPI_1_NAME, spi_qmsi_init,
|
||||
DEVICE_PM_OPS_GET(spi_master), &spi_qmsi_mst_1_runtime,
|
||||
&spi_qmsi_mst_1_config, SECONDARY, CONFIG_SPI_INIT_PRIORITY);
|
||||
DEVICE_DEFINE(spi_master_1, CONFIG_SPI_1_NAME, spi_qmsi_init,
|
||||
spi_master_qmsi_device_ctrl, &spi_qmsi_mst_1_runtime,
|
||||
&spi_qmsi_mst_1_config, SECONDARY, CONFIG_SPI_INIT_PRIORITY,
|
||||
NULL);
|
||||
#endif /* CONFIG_SPI_1 */
|
||||
|
|
|
@ -157,6 +157,12 @@ static bool timer_known_to_have_expired;
|
|||
static unsigned char timer_mode = TIMER_MODE_PERIODIC;
|
||||
#endif /* CONFIG_TICKLESS_IDLE */
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
static uint32_t loapic_timer_device_power_state;
|
||||
static uint32_t reg_timer_save;
|
||||
static uint32_t reg_timer_cfg_save;
|
||||
#endif
|
||||
|
||||
/* externs */
|
||||
|
||||
#if !defined(CONFIG_KERNEL_V2)
|
||||
|
@ -536,7 +542,9 @@ int _sys_clock_driver_init(struct device *device)
|
|||
#endif
|
||||
initial_count_register_set(cycles_per_tick - 1);
|
||||
periodic_mode_set();
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
loapic_timer_device_power_state = DEVICE_PM_ACTIVE_STATE;
|
||||
#endif
|
||||
IRQ_CONNECT(TIMER_IRQ, TIMER_IRQ_PRIORITY, _timer_int_handler, 0, 0);
|
||||
|
||||
/* Everything has been configured. It is now safe to enable the
|
||||
|
@ -549,54 +557,70 @@ int _sys_clock_driver_init(struct device *device)
|
|||
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
|
||||
static uint32_t reg_timer_save;
|
||||
static uint32_t reg_timer_cfg_save;
|
||||
|
||||
int _sys_clock_suspend(struct device *dev, int pm_policy)
|
||||
static int sys_clock_suspend(struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
reg_timer_save = *_REG_TIMER;
|
||||
reg_timer_cfg_save = *_REG_TIMER_CFG;
|
||||
}
|
||||
reg_timer_save = *_REG_TIMER;
|
||||
reg_timer_cfg_save = *_REG_TIMER_CFG;
|
||||
|
||||
loapic_timer_device_power_state = DEVICE_PM_SUSPEND_STATE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _sys_clock_resume(struct device *dev, int pm_policy)
|
||||
static int sys_clock_resume(struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
*_REG_TIMER = reg_timer_save;
|
||||
*_REG_TIMER_CFG = reg_timer_cfg_save;
|
||||
*_REG_TIMER = reg_timer_save;
|
||||
*_REG_TIMER_CFG = reg_timer_cfg_save;
|
||||
|
||||
/*
|
||||
* It is difficult to accurately know the time spent in DS.
|
||||
* We can use TSC or RTC but that will create a dependency
|
||||
* on those components. Other issue is about what to do
|
||||
* with pending timers. Following are some options :-
|
||||
*
|
||||
* 1) Expire all timers based on time spent found using some
|
||||
* source like TSC
|
||||
* 2) Expire all timers anyway
|
||||
* 3) Expire only the timer at the top
|
||||
* 4) Contine from where the timer left
|
||||
*
|
||||
* 1 and 2 require change to how timers are handled. 4 may not
|
||||
* give a good user experience. After waiting for a long period
|
||||
* in DS, the system would appear dead if it waits again.
|
||||
*
|
||||
* Current implementation uses option 3. The top most timer is
|
||||
* expired. Following code will set the counter to a low number
|
||||
* so it would immediately expire and generate timer interrupt
|
||||
* which will process the top most timer. Note that timer IC
|
||||
* cannot be set to 0. Setting it to 0 will stop the timer.
|
||||
*/
|
||||
/*
|
||||
* It is difficult to accurately know the time spent in DS.
|
||||
* We can use TSC or RTC but that will create a dependency
|
||||
* on those components. Other issue is about what to do
|
||||
* with pending timers. Following are some options :-
|
||||
*
|
||||
* 1) Expire all timers based on time spent found using some
|
||||
* source like TSC
|
||||
* 2) Expire all timers anyway
|
||||
* 3) Expire only the timer at the top
|
||||
* 4) Contine from where the timer left
|
||||
*
|
||||
* 1 and 2 require change to how timers are handled. 4 may not
|
||||
* give a good user experience. After waiting for a long period
|
||||
* in DS, the system would appear dead if it waits again.
|
||||
*
|
||||
* Current implementation uses option 3. The top most timer is
|
||||
* expired. Following code will set the counter to a low number
|
||||
* so it would immediately expire and generate timer interrupt
|
||||
* which will process the top most timer. Note that timer IC
|
||||
* cannot be set to 0. Setting it to 0 will stop the timer.
|
||||
*/
|
||||
|
||||
initial_count_register_set(1);
|
||||
initial_count_register_set(1);
|
||||
loapic_timer_device_power_state = DEVICE_PM_ACTIVE_STATE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
int sys_clock_device_ctrl(struct device *port, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return sys_clock_suspend(port);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return sys_clock_resume(port);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = loapic_timer_device_power_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -32,15 +32,6 @@
|
|||
#include <init.h>
|
||||
#include <drivers/system_timer.h>
|
||||
|
||||
/*
|
||||
* Currently only loapic timer implements device pm ops.
|
||||
* For other timers, define device_pm_ops with default handers in case
|
||||
* the app enables CONFIG_DEVICE_POWER_MANAGEMENT.
|
||||
*/
|
||||
#ifdef CONFIG_LOAPIC_TIMER
|
||||
DEFINE_DEVICE_PM_OPS(_sys_clock, _sys_clock_suspend, _sys_clock_resume);
|
||||
#else
|
||||
DEFINE_DEVICE_PM_OPS(_sys_clock, device_pm_nop, device_pm_nop);
|
||||
#endif
|
||||
SYS_INIT_PM("sys_clock", _sys_clock_driver_init, DEVICE_PM_OPS_GET(_sys_clock),
|
||||
SECONDARY, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);
|
||||
SYS_DEVICE_DEFINE("sys_clock", _sys_clock_driver_init,
|
||||
sys_clock_device_ctrl, SECONDARY,
|
||||
CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
struct wdt_data {
|
||||
struct nano_sem sem;
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WDT_QMSI_API_REENTRANCY
|
||||
|
@ -134,6 +137,81 @@ static struct wdt_driver_api api = {
|
|||
.reload = reload,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
struct wdt_ctx {
|
||||
uint32_t wdt_cr;
|
||||
uint32_t wdt_torr;
|
||||
uint32_t int_watchdog_mask;
|
||||
};
|
||||
|
||||
static struct wdt_ctx wdt_ctx_save;
|
||||
|
||||
|
||||
static void wdt_qmsi_set_power_state(struct device *dev, uint32_t power_state)
|
||||
{
|
||||
struct wdt_data *context = dev->driver_data;
|
||||
|
||||
context->device_power_state = power_state;
|
||||
}
|
||||
|
||||
static uint32_t wdt_qmsi_get_power_state(struct device *dev)
|
||||
{
|
||||
struct wdt_data *context = dev->driver_data;
|
||||
|
||||
return context->device_power_state;
|
||||
}
|
||||
|
||||
|
||||
static int wdt_suspend_device(struct device *dev)
|
||||
{
|
||||
wdt_ctx_save.wdt_torr = QM_WDT[QM_WDT_0].wdt_torr;
|
||||
wdt_ctx_save.wdt_cr = QM_WDT[QM_WDT_0].wdt_cr;
|
||||
wdt_ctx_save.int_watchdog_mask =
|
||||
QM_SCSS_INT->int_watchdog_mask;
|
||||
|
||||
wdt_qmsi_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wdt_resume_device_from_suspend(struct device *dev)
|
||||
{
|
||||
/* TOP_INIT field has to be written before
|
||||
* the Watchdog Timer is enabled.
|
||||
*/
|
||||
QM_WDT[QM_WDT_0].wdt_torr = wdt_ctx_save.wdt_torr;
|
||||
QM_WDT[QM_WDT_0].wdt_cr = wdt_ctx_save.wdt_cr;
|
||||
QM_SCSS_INT->int_watchdog_mask = wdt_ctx_save.int_watchdog_mask;
|
||||
|
||||
wdt_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the driver control management functionality
|
||||
* the *context may include IN data or/and OUT data
|
||||
*/
|
||||
static int wdt_qmsi_device_ctrl(struct device *dev, uint32_t ctrl_command,
|
||||
void *context)
|
||||
{
|
||||
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
|
||||
return wdt_suspend_device(dev);
|
||||
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
|
||||
return wdt_resume_device_from_suspend(dev);
|
||||
}
|
||||
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
|
||||
*((uint32_t *)context) = wdt_qmsi_get_power_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define wdt_qmsi_set_power_state(...)
|
||||
#endif
|
||||
|
||||
static int init(struct device *dev)
|
||||
{
|
||||
wdt_reentrancy_init(dev);
|
||||
|
@ -147,48 +225,10 @@ static int init(struct device *dev)
|
|||
/* Route watchdog interrupt to Lakemont */
|
||||
QM_SCSS_INT->int_watchdog_mask &= ~BIT(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
struct wdt_ctx {
|
||||
uint32_t wdt_cr;
|
||||
uint32_t wdt_torr;
|
||||
uint32_t int_watchdog_mask;
|
||||
};
|
||||
|
||||
static struct wdt_ctx wdt_ctx_save;
|
||||
|
||||
static int wdt_suspend_device(struct device *dev, int pm_policy)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
wdt_ctx_save.wdt_torr = QM_WDT[QM_WDT_0].wdt_torr;
|
||||
wdt_ctx_save.wdt_cr = QM_WDT[QM_WDT_0].wdt_cr;
|
||||
wdt_ctx_save.int_watchdog_mask =
|
||||
QM_SCSS_INT->int_watchdog_mask;
|
||||
}
|
||||
wdt_qmsi_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wdt_resume_device(struct device *dev, int pm_policy)
|
||||
{
|
||||
if (pm_policy == SYS_PM_DEEP_SLEEP) {
|
||||
/* TOP_INIT field has to be written before
|
||||
* the Watchdog Timer is enabled.
|
||||
*/
|
||||
QM_WDT[QM_WDT_0].wdt_torr = wdt_ctx_save.wdt_torr;
|
||||
QM_WDT[QM_WDT_0].wdt_cr = wdt_ctx_save.wdt_cr;
|
||||
QM_SCSS_INT->int_watchdog_mask =
|
||||
wdt_ctx_save.int_watchdog_mask;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICE_PM_OPS(wdt, wdt_suspend_device, wdt_resume_device);
|
||||
|
||||
DEVICE_AND_API_INIT_PM(wdt, CONFIG_WDT_0_NAME, init, DEVICE_PM_OPS_GET(wdt),
|
||||
WDT_CONTEXT, 0, PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
(void *)&api);
|
||||
DEVICE_DEFINE(wdt, CONFIG_WDT_0_NAME, init, wdt_qmsi_device_ctrl, WDT_CONTEXT,
|
||||
0, PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, (void *)&api);
|
||||
|
|
|
@ -59,8 +59,17 @@ extern uint32_t _nano_get_earliest_deadline(void);
|
|||
|
||||
extern void _nano_sys_clock_tick_announce(int32_t ticks);
|
||||
|
||||
extern int _sys_clock_suspend(struct device *dev, int pm_policy);
|
||||
extern int _sys_clock_resume(struct device *dev, int pm_policy);
|
||||
extern int sys_clock_device_ctrl(struct device *device,
|
||||
uint32_t ctrl_command, void *context);
|
||||
|
||||
/*
|
||||
* Currently regarding timers, only loapic timer implements
|
||||
* device pm functionality. For other timers, use default handler in case
|
||||
* the app enables CONFIG_DEVICE_POWER_MANAGEMENT.
|
||||
*/
|
||||
#ifndef CONFIG_LOAPIC_TIMER
|
||||
#define sys_clock_device_ctrl device_control_nop
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_KERNEL_V2) && defined(CONFIG_MICROKERNEL)
|
||||
extern void (*_do_sys_clock_tick_announce)(kevent_t);
|
||||
|
|
|
@ -296,7 +296,8 @@ static void suspend_devices(int pm_policy)
|
|||
* device in the policy list is busy as shown below :
|
||||
* if(device_busy_check(&device_list[idx])) {do something}
|
||||
*/
|
||||
device_retval[i] = device_suspend(&device_list[idx], pm_policy);
|
||||
device_retval[i] = device_set_power_state(&device_list[idx],
|
||||
DEVICE_PM_SUSPEND_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,8 +308,8 @@ static void resume_devices(int pm_policy)
|
|||
for (i = 0; i < device_count; i++) {
|
||||
if (!device_retval[i]) {
|
||||
int idx = device_policy_list[i];
|
||||
|
||||
device_resume(&device_list[idx], pm_policy);
|
||||
device_set_power_state(&device_list[idx],
|
||||
DEVICE_PM_ACTIVE_STATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,15 +154,16 @@ static void do_soc_sleep(int deep)
|
|||
set_rtc_alarm();
|
||||
|
||||
for (i = suspend_device_count - 1; i >= 0; i--) {
|
||||
devices_retval[i] = device_suspend(suspend_devices[i],
|
||||
SYS_PM_DEEP_SLEEP);
|
||||
devices_retval[i] = device_set_power_state(suspend_devices[i],
|
||||
DEVICE_PM_SUSPEND_STATE);
|
||||
}
|
||||
|
||||
__do_soc_sleep(deep);
|
||||
|
||||
for (i = 0; i < suspend_device_count; i++) {
|
||||
if (!devices_retval[i]) {
|
||||
device_resume(suspend_devices[i], SYS_PM_DEEP_SLEEP);
|
||||
device_set_power_state(suspend_devices[i],
|
||||
DEVICE_PM_ACTIVE_STATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue