diff options
Diffstat (limited to 'drivers/gpio/gpio-omap.c')
| -rw-r--r-- | drivers/gpio/gpio-omap.c | 34 | 
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index afef0f7c8ad..c48de8ffe9e 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1206,8 +1206,30 @@ static int omap_gpio_runtime_suspend(struct device *dev)  	struct gpio_bank *bank = platform_get_drvdata(pdev);  	u32 l1 = 0, l2 = 0;  	unsigned long flags; +	u32 wake_low, wake_hi;  	spin_lock_irqsave(&bank->lock, flags); + +	/* +	 * Only edges can generate a wakeup event to the PRCM. +	 * +	 * Therefore, ensure any wake-up capable GPIOs have +	 * edge-detection enabled before going idle to ensure a wakeup +	 * to the PRCM is generated on a GPIO transition. (c.f. 34xx +	 * NDA TRM 25.5.3.1) +	 * +	 * The normal values will be restored upon ->runtime_resume() +	 * by writing back the values saved in bank->context. +	 */ +	wake_low = bank->context.leveldetect0 & bank->context.wake_en; +	if (wake_low) +		__raw_writel(wake_low | bank->context.fallingdetect, +			     bank->base + bank->regs->fallingdetect); +	wake_hi = bank->context.leveldetect1 & bank->context.wake_en; +	if (wake_hi) +		__raw_writel(wake_hi | bank->context.risingdetect, +			     bank->base + bank->regs->risingdetect); +  	if (bank->power_mode != OFF_MODE) {  		bank->power_mode = 0;  		goto update_gpio_context_count; @@ -1256,6 +1278,18 @@ static int omap_gpio_runtime_resume(struct device *dev)  	spin_lock_irqsave(&bank->lock, flags);  	_gpio_dbck_enable(bank); + +	/* +	 * In ->runtime_suspend(), level-triggered, wakeup-enabled +	 * GPIOs were set to edge trigger also in order to be able to +	 * generate a PRCM wakeup.  Here we restore the +	 * pre-runtime_suspend() values for edge triggering. +	 */ +	__raw_writel(bank->context.fallingdetect, +		     bank->base + bank->regs->fallingdetect); +	__raw_writel(bank->context.risingdetect, +		     bank->base + bank->regs->risingdetect); +  	if (!bank->enabled_non_wakeup_gpios || !bank->workaround_enabled) {  		spin_unlock_irqrestore(&bank->lock, flags);  		return 0;  |