gpio_qmsi: Add suspend/resume

In order to restore GPIO context after entering
SYS_PM_DEEP_SLEEP, the suspend and resume
functions for GPIO and GPOIO_AON are called. The
following parameters are restored:
- All non-sticky RW registers for the GPIO device.
- The MASK register (interrupt routing register).

Note: No need to sve/resume AON_GPIO registers as
they all are sticky registers.

The suspend/resume functionality is implemented in
the QMSI shim layer as a fast and temporary solution,
it will be removed and migrated to QMSI later.

Change-Id: I68e25c9da4bb8ea65f312e3686d9ef090cb775ff
Signed-off-by: Dragan Cvetic <dragan.cvetic@intel.com>
This commit is contained in:
Dragan Cvetic 2016-07-22 01:19:49 +01:00 committed by Inaky Perez-Gonzalez
commit 021e09251a

View file

@ -28,6 +28,7 @@
#include "gpio_api_compat.h" #include "gpio_api_compat.h"
#include "qm_isr.h" #include "qm_isr.h"
#include "clk.h" #include "clk.h"
#include <power.h>
struct gpio_qmsi_config { struct gpio_qmsi_config {
qm_gpio_t gpio; qm_gpio_t gpio;
@ -88,11 +89,54 @@ static struct gpio_qmsi_config gpio_0_config = {
static struct gpio_qmsi_runtime gpio_0_runtime; static struct gpio_qmsi_runtime gpio_0_runtime;
DEVICE_INIT(gpio_0, CONFIG_GPIO_QMSI_0_NAME, &gpio_qmsi_init, #ifdef CONFIG_DEVICE_POWER_MANAGEMENT
&gpio_0_runtime, &gpio_0_config, QM_RW uint32_t save_reg[10];
SECONDARY, CONFIG_GPIO_QMSI_INIT_PRIORITY); static uint32_t int_gpio_mask_save;
GPIO_SETUP_COMPAT_DEV(gpio_0);
static int gpio_suspend_device(struct device *dev, int pm_policy)
{
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);
}
return 0;
}
static int gpio_resume_device(struct device *dev, int pm_policy)
{
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;
}
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);
GPIO_SETUP_COMPAT_DEV(gpio_0);
#endif /* CONFIG_GPIO_QMSI_0 */ #endif /* CONFIG_GPIO_QMSI_0 */
#ifdef CONFIG_GPIO_QMSI_AON #ifdef CONFIG_GPIO_QMSI_AON
@ -103,9 +147,34 @@ static struct gpio_qmsi_config gpio_aon_config = {
static struct gpio_qmsi_runtime gpio_aon_runtime; static struct gpio_qmsi_runtime gpio_aon_runtime;
DEVICE_INIT(gpio_aon, CONFIG_GPIO_QMSI_AON_NAME, &gpio_qmsi_init,
&gpio_aon_runtime, &gpio_aon_config, #ifdef CONFIG_DEVICE_POWER_MANAGEMENT
SECONDARY, CONFIG_GPIO_QMSI_INIT_PRIORITY); static uint32_t int_gpio_aon_mask_save;
static int gpio_aon_suspend_device(struct device *dev, int pm_policy)
{
if (pm_policy == SYS_PM_DEEP_SLEEP) {
int_gpio_aon_mask_save =
REG_VAL(&QM_SCSS_INT->int_aon_gpio_mask);
}
return 0;
}
static int gpio_aon_resume_device(struct device *dev, int pm_policy)
{
if (pm_policy == SYS_PM_DEEP_SLEEP) {
REG_VAL(&QM_SCSS_INT->int_aon_gpio_mask) =
int_gpio_aon_mask_save;
}
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);
GPIO_SETUP_COMPAT_DEV(gpio_aon); GPIO_SETUP_COMPAT_DEV(gpio_aon);
#endif /* CONFIG_GPIO_QMSI_AON */ #endif /* CONFIG_GPIO_QMSI_AON */