[Gta04-owner] Linux 3.5 on GTA04

NeilBrown neilb at suse.de
Sat Aug 25 13:42:26 CEST 2012


On Fri, 24 Aug 2012 17:27:47 +1000 NeilBrown <neilb at suse.de> wrote:

> > Btw have you noticed that in 3.4 or 3.5 kernel you can wake the device from 
> > suspend with touchscreen?
> 
> No I hadn't.  My phone is configured to enter suspend immediately whenever
> there is not a good reason to be awake (and e.g. power button press means
> there is good reason to be awake for 15 seconds - screen taps extend that
> etc).
> So I would only notice by increased power consumption - which I have noticed
> occasionally - or close inspection of the logs - which I haven't.
> 
> Having examined the code it doesn't look like it is trivial to fix.
> The wakeup-enable is deliberately turned on so that the CPU can go into deep
> sleep when idle (if off_mode is enabled) and still be woken up by interrupts.
> We do want this.
> But that 'wakeup-enable-for-deep-sleep' flag has been confused with the
> 'wakeup-enable-for-suspend' flag.  I'll need to separate them so a screen tap
> will wake the CPU if it is sleeping for a few milliseconds between taps, but
> not if it is suspended and in my pocket.
> This recent patch:
> 
> commit 0aa2727399c0b78225021413022c164cb99fbc5e
> Author: Tarun Kanti DebBarma <tarun.kanti at ti.com>
> Date:   Fri Apr 27 19:43:33 2012 +0530
> 
>     gpio/omap: remove suspend_wakeup field from struct gpio_bank
> 
> looks interesting.  It appears to be removing the functionality that I think
> I want to add!!  It is a little different though so I isn't simply a case
> that someone broke something.  I'm not sure when I get to drill into this as
> I'll be at conferences in San Diego all next week :-)
>

Who wants to pack, when you can code!!

This patch looks good and fixes the bug for me.  I'll send it upstream
shortly.  It is already in my 3.5 branch.

From fa4f96599cdb2a84d90bd0394e8b8a92d6dbea31 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb at suse.de>
Date: Sat, 25 Aug 2012 21:39:14 +1000
Subject: [PATCH] OMAP GPIO - don't wake from suspend unless requested.

Current kernel will wake from suspend on an event an any active
GPIO event if enable_irq_wake() wasn't called.

There are two reasons that the hardware wake-enable bit should be set:

1/ while non-suspended the CPU might go into a deep sleep (off_mode)
  in which the wake-enable bit is needed for an interrupt to be
  recognised.
2/ while suspended the GPIO interrupt should wake from suspend if and
   only if irq_wake as been enabled.

The code currently doesn't keep these two reasons separate so they get
confused and sometimes the wakeup flags is set incorrectly.

This patch reverts:
 commit 9c4ed9e6c01e7a8bd9079da8267e1f03cb4761fc
    gpio/omap: remove suspend/resume callbacks
and
 commit 0aa2727399c0b78225021413022c164cb99fbc5e
    gpio/omap: remove suspend_wakeup field from struct gpio_bank

and makes some minor changes so that we have separate flags for "GPIO
should wake from deep idle" and "GPIO should wake from suspend".

With this patch, the GPIO from my touch screen doesn't wake my device
any more, which is what I want.

Cc: Kevin Hilman <khilman at ti.com>
Cc: Tony Lindgren <tony at atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar at ti.com>
Cc: Cousson, Benoit <b-cousson at ti.com>
Cc: Grant Likely <grant.likely at secretlab.ca>
Cc: Tarun Kanti DebBarma <tarun.kanti at ti.com>
Cc: Felipe Balbi <balbi at ti.com>
Cc: Govindraj.R <govindraj.raja at ti.com>

Signed-off-by: NeilBrown <neilb at suse.de>

diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 4fbc208..fdbad70 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -57,6 +57,7 @@ struct gpio_bank {
 	u16 irq;
 	int irq_base;
 	struct irq_domain *domain;
+	u32 suspend_wakeup;
 	u32 non_wakeup_gpios;
 	u32 enabled_non_wakeup_gpios;
 	struct gpio_regs context;
@@ -522,11 +523,12 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
 
 	spin_lock_irqsave(&bank->lock, flags);
 	if (enable)
-		bank->context.wake_en |= gpio_bit;
+		bank->suspend_wakeup |= gpio_bit;
 	else
-		bank->context.wake_en &= ~gpio_bit;
+		bank->suspend_wakeup &= ~gpio_bit;
 
-	__raw_writel(bank->context.wake_en, bank->base + bank->regs->wkup_en);
+	if (!bank->loses_context)
+		__raw_writel(bank->suspend_wakeup, bank->base + bank->regs->wkup_en);
 	spin_unlock_irqrestore(&bank->lock, flags);
 
 	return 0;
@@ -1157,6 +1159,51 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 #ifdef CONFIG_ARCH_OMAP2PLUS
 
 #if defined(CONFIG_PM_RUNTIME)
+
+#if defined(CONFIG_PM_SLEEP)
+static int omap_gpio_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_bank *bank = platform_get_drvdata(pdev);
+	void __iomem *base = bank->base;
+	unsigned long flags;
+
+	if (!bank->mod_usage || !bank->loses_context)
+		return 0;
+
+	if (!bank->regs->wkup_en || !bank->context.wake_en)
+		return 0;
+
+	spin_lock_irqsave(&bank->lock, flags);
+	_gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0);
+	_gpio_rmw(base, bank->regs->wkup_en, bank->suspend_wakeup, 1);
+	spin_unlock_irqrestore(&bank->lock, flags);
+
+	return 0;
+}
+
+static int omap_gpio_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_bank *bank = platform_get_drvdata(pdev);
+	void __iomem *base = bank->base;
+	unsigned long flags;
+
+	if (!bank->mod_usage || !bank->loses_context)
+		return 0;
+
+	if (!bank->regs->wkup_en || !bank->context.wake_en)
+		return 0;
+
+	spin_lock_irqsave(&bank->lock, flags);
+	_gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0);
+	_gpio_rmw(base, bank->regs->wkup_en, bank->context.wake_en, 1);
+	spin_unlock_irqrestore(&bank->lock, flags);
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
 static void omap_gpio_restore_context(struct gpio_bank *bank);
 
 static int omap_gpio_runtime_suspend(struct device *dev)
@@ -1386,11 +1433,14 @@ static void omap_gpio_restore_context(struct gpio_bank *bank)
 }
 #endif /* CONFIG_PM_RUNTIME */
 #else
+#define omap_gpio_suspend NULL
+#define omap_gpio_resume NULL
 #define omap_gpio_runtime_suspend NULL
 #define omap_gpio_runtime_resume NULL
 #endif
 
 static const struct dev_pm_ops gpio_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(omap_gpio_suspend, omap_gpio_resume)
 	SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume,
 									NULL)
 };
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 828 bytes
Desc: not available
URL: <http://lists.goldelico.com/pipermail/gta04-owner/attachments/20120825/29ca583f/attachment.bin>


More information about the Gta04-owner mailing list