adc_qmsi_ss: Add power management support to driver

Add the device_ctrl hook to the ADC driver of the Sensor Subsystem,
using the QMSI APIs to save and restore the driver's context.

Jira: ZEP-667

Change-Id: I8b89a875d8185cc4db3c4bfc30ef0f39c6589df1
Signed-off-by: Iván Briano <ivan.briano@intel.com>
This commit is contained in:
Iván Briano 2016-11-09 13:42:13 -02:00 committed by Anas Nashif
commit b190bd4da2

View file

@ -40,6 +40,12 @@ struct adc_info {
atomic_t state; atomic_t state;
device_sync_call_t sync; device_sync_call_t sync;
struct k_sem sem; struct k_sem sem;
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
uint32_t device_power_state;
#ifdef CONFIG_SYS_POWER_DEEP_SLEEP
qm_ss_adc_context_t adc_ctx;
#endif
#endif
}; };
static void adc_config_irq(void); static void adc_config_irq(void);
@ -243,13 +249,70 @@ static const struct adc_driver_api api_funcs = {
.read = adc_qmsi_ss_read, .read = adc_qmsi_ss_read,
}; };
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
static void adc_qmsi_ss_set_power_state(struct device *dev,
uint32_t power_state)
{
struct adc_info *context = dev->driver_data;
context->device_power_state = power_state;
}
static uint32_t adc_qmsi_ss_get_power_state(struct device *dev)
{
struct adc_info *context = dev->driver_data;
return context->device_power_state;
}
#if CONFIG_SYS_POWER_DEEP_SLEEP
static int adc_qmsi_ss_suspend_device(struct device *dev)
{
struct adc_info *context = dev->driver_data;
qm_ss_adc_save_context(QM_SS_ADC_0, &context->adc_ctx);
adc_qmsi_ss_set_power_state(dev, DEVICE_PM_SUSPEND_STATE);
return 0;
}
static int adc_qmsi_ss_resume_device_from_suspend(struct device *dev)
{
struct adc_info *context = dev->driver_data;
qm_ss_adc_restore_context(QM_SS_ADC_0, &context->adc_ctx);
adc_qmsi_ss_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
return 0;
}
#endif /* CONFIG_SYS_POWER_DEEP_SLEEP */
static int adc_qmsi_ss_device_ctrl(struct device *dev, uint32_t ctrl_command,
void *context)
{
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
#ifdef CONFIG_SYS_POWER_DEEP_SLEEP
if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) {
return adc_qmsi_ss_suspend_device(dev);
} else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) {
return adc_qmsi_ss_resume_device_from_suspend(dev);
}
#endif
} else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) {
*((uint32_t *)context) = adc_qmsi_ss_get_power_state(dev);
}
return 0;
}
#else
#define adc_qmsi_ss_set_power_state(...)
#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */
int adc_qmsi_ss_init(struct device *dev) int adc_qmsi_ss_init(struct device *dev)
{ {
struct adc_info *info = dev->driver_data; struct adc_info *info = dev->driver_data;
dev->driver_api = &api_funcs;
/* Set up config */ /* Set up config */
/* Clock cycles between the start of each sample */ /* Clock cycles between the start of each sample */
cfg.window = CONFIG_ADC_QMSI_SERIAL_DELAY; cfg.window = CONFIG_ADC_QMSI_SERIAL_DELAY;
@ -267,14 +330,16 @@ int adc_qmsi_ss_init(struct device *dev)
adc_config_irq(); adc_config_irq();
adc_qmsi_ss_set_power_state(dev, DEVICE_PM_ACTIVE_STATE);
return 0; return 0;
} }
struct adc_info adc_info_dev; struct adc_info adc_info_dev;
DEVICE_INIT(adc_qmsi_ss, CONFIG_ADC_0_NAME, &adc_qmsi_ss_init, DEVICE_DEFINE(adc_qmsi_ss, CONFIG_ADC_0_NAME, &adc_qmsi_ss_init,
&adc_info_dev, NULL, adc_qmsi_ss_device_ctrl, &adc_info_dev, NULL, POST_KERNEL,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &api_funcs);
static void adc_config_irq(void) static void adc_config_irq(void)
{ {