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:
parent
9d033295ee
commit
021e09251a
1 changed files with 76 additions and 7 deletions
|
@ -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 */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue