All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Brownell <david-b@pacbell.net>
To: Tony Lindgren <tony@atomide.com>
Cc: linux-omap-open-source@linux.omap.com
Subject: Re: [patch 2.6.17-rc4-omap-git] rtc-omap, rtc framework driver
Date: Wed, 30 Aug 2006 01:22:13 -0700	[thread overview]
Message-ID: <200608300122.14254.david-b@pacbell.net> (raw)
In-Reply-To: <20060830075733.GH27668@atomide.com>

[-- Attachment #1: Type: text/plain, Size: 628 bytes --]

On Wednesday 30 August 2006 12:57 am, Tony Lindgren wrote:
> * David Brownell <david-b@pacbell.net> [060829 22:52]:
> > On Tuesday 29 August 2006 7:34 am, Tony Lindgren wrote:
> > > 
> > > Sounds like it should be capable of waking up the system if 32KHz clock
> > > is on and the wake-up events are configured properly.
> > 
> > Yes.  I had more of a look at things, and have a patch (yet to be tested)
> > that should let many more things be wakeup event sources.  MPUIO irqs,
> > GPIOs not in the first bank, non-MPUI/GPIO irqs (like RTC), etc.
> 
> Cool. 

hmm, not sure when I'll have a chance to test it, so here it is...

[-- Attachment #2: wake.patch --]
[-- Type: text/x-diff, Size: 8747 bytes --]

Handle wakeup irqs more correctly and completely ... the set of wakeup
events is dynmically specified, not statically, and any IRQ is eligible.

 - (PLATFORM) Add/use MPUIO/ARMIO wakeup event handling, as for GPIO.

 - (PLATFORM) Enabling a GPIO or MPUIO irq as a wakeup event source
   automatically enables its parent MPU L1 or L2 IRQ; this is easy
   now that wakeup enables/disables are properly refcounted.

 - (OMAP1) Move pm wakeup event setup from pm.c into irq.c so that it can
   obey driver {en,dis}able_irq_wake() calls ... so now any L1 or L2
   IRQ source can be a wakeup event, not just a small static group.
   
 - (OMAP1) Only L1->L2 cascades are always marked as wakeup sources.

This means that drivers can now use /sys/devices/.../power/wakeup userspace
configuration for board-specific policies about activating wakeup sources.

UNTESTED.

TODO:  Various drivers, notably the keypad driver, need to learn about
being device_can_wakeup() and {en,dis}able_irq_wake().



Index: osk2/arch/arm/plat-omap/gpio.c
===================================================================
--- osk2.orig/arch/arm/plat-omap/gpio.c	2006-08-29 09:02:28.000000000 -0700
+++ osk2/arch/arm/plat-omap/gpio.c	2006-08-29 09:15:37.000000000 -0700
@@ -646,13 +646,17 @@ static inline void _set_gpio_irqenable(s
 static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
 {
 	switch (bank->method) {
+	case METHOD_MPUIO:
 	case METHOD_GPIO_1610:
 	case METHOD_GPIO_24XX:
 		spin_lock(&bank->lock);
-		if (enable)
+		if (enable) {
 			bank->suspend_wakeup |= (1 << gpio);
-		else
+			enable_irq_wake(bank->irq);
+		} else {
 			bank->suspend_wakeup &= ~(1 << gpio);
+			disable_irq_wake(bank->irq);
+		}
 		spin_unlock(&bank->lock);
 		return 0;
 	default:
@@ -945,6 +949,21 @@ static void gpio_unmask_irq(unsigned int
 	_set_gpio_irqenable(bank, gpio_idx, 1);
 }
 
+static struct irq_chip gpio_irq_chip = {
+	.name		= "GPIO",
+	.startup	= gpio_irq_startup,
+	.shutdown	= gpio_irq_shutdown,
+	.ack		= gpio_ack_irq,
+	.mask		= gpio_mask_irq,
+	.unmask		= gpio_unmask_irq,
+	.set_type	= gpio_irq_type,
+	.set_wake	= gpio_wake_enable,
+};
+
+/*---------------------------------------------------------------------*/
+
+#ifndef	CONFIG_ARCH_OMAP24XX
+
 static void mpuio_ack_irq(unsigned int irq)
 {
 	/* The ISR is reset automatically, so do nothing here. */
@@ -966,24 +985,46 @@ static void mpuio_unmask_irq(unsigned in
 	_set_gpio_irqenable(bank, gpio, 1);
 }
 
-static struct irq_chip gpio_irq_chip = {
-	.name		= "GPIO",
-	.startup	= gpio_irq_startup,
-	.shutdown	= gpio_irq_shutdown,
-	.ack		= gpio_ack_irq,
-	.mask		= gpio_mask_irq,
-	.unmask		= gpio_unmask_irq,
-	.set_type	= gpio_irq_type,
+static struct irq_chip mpuio_irq_chip = {
+	.name		= "MPUIO",
+	.ack		= mpuio_ack_irq,
+	.mask		= mpuio_mask_irq,
+	.unmask		= mpuio_unmask_irq,
 	.set_wake	= gpio_wake_enable,
 };
 
-static struct irq_chip mpuio_irq_chip = {
-	.name	= "MPUIO",
-	.ack	= mpuio_ack_irq,
-	.mask	= mpuio_mask_irq,
-	.unmask	= mpuio_unmask_irq
+static int omap_mpuio_suspend(struct sys_device *dev, pm_message_t mesg)
+{
+	void __iomem	*reg = gpio_bank[0].base + OMAP_MPUIO_GPIO_MASKIT;
+
+	gpio_bank[0].saved_wakeup = __raw_readw(reg);
+	__raw_writew(~gpio_bank[0].suspend_wakeup, reg);
+	return 0;
+}
+
+static int omap_mpuio_resume(struct sys_device *dev)
+{
+	void __iomem	*reg = gpio_bank[0].base + OMAP_MPUIO_GPIO_MASKIT;
+
+	__raw_writew(gpio_bank[0].saved_wakeup, reg);
+	return 0;
+}
+
+static struct sysdev_class omap_mpuio_sysclass = {
+	set_kset_name("mpuio"),
+	.suspend	= omap_mpuio_suspend,
+	.resume		= omap_mpuio_resume,
+};
+
+static struct sys_device omap_mpuio_device = {
+	.id		= 0,
+	.cls		= &omap_mpuio_sysclass,
 };
 
+#endif
+
+/*---------------------------------------------------------------------*/
+
 static int initialized;
 static struct clk * gpio_ick;
 static struct clk * gpio_fck;
@@ -1215,6 +1256,14 @@ static int __init omap_gpio_sysinit(void
 	if (!initialized)
 		ret = _omap_gpio_init();
 
+#ifndef	CONFIG_ARCH_OMAP24XX
+	if (ret == 0) {
+		ret = sysdev_class_register(&omap_mpuio_sysclass);
+		if (ret == 0)
+			ret = sysdev_register(&omap_mpuio_device);
+	}
+#endif
+
 #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX)
 	if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
 		if (ret == 0) {
Index: osk2/arch/arm/mach-omap1/irq.c
===================================================================
--- osk2.orig/arch/arm/mach-omap1/irq.c	2006-08-29 09:02:27.000000000 -0700
+++ osk2/arch/arm/mach-omap1/irq.c	2006-08-29 09:08:38.000000000 -0700
@@ -118,6 +118,39 @@ static int omap_wake_irq(unsigned int ir
 	return 0;
 }
 
+#ifdef	CONFIG_PM
+
+/* enable_irq_wake() calls from drivers will normally be configured
+ * based on /sys/devices/.../power/wakeup settings, for drivers that
+ * that support wakeup events.
+ */
+void omap_pm_wakeup_setup(void)
+{
+	/* MPU level 1 controller ... take driver settings, plus
+	 * L1->L2 cascade ... GPIO and MPUIO handled via sysdev
+	 */
+	omap_writel(~irq_banks[0].wake_enable, OMAP_IH1_MIR);
+
+	/* MPU level 2 controller ... take driver settings, plus for
+	 * omap730 and omap16xx peripheral wakeup (enabled by irq setup)
+	 */
+	omap_writel(~irq_banks[1].wake_enable, OMAP_IH2_0_MIR);
+
+	if (cpu_is_omap730()) {
+		omap_writel(~irq_banks[1].wake_enable, OMAP_IH2_1_MIR);
+	}
+	if (cpu_is_omap16xx()) {
+		omap_writel(~irq_banks[1].wake_enable, OMAP_IH2_1_MIR);
+		omap_writel(~irq_banks[3].wake_enable, OMAP_IH2_2_MIR);
+		omap_writel(~irq_banks[4].wake_enable, OMAP_IH2_3_MIR);
+	}
+
+	/* New IRQ agreement, recalculate in cascade order */
+	omap_writel(1, OMAP_IH2_CONTROL);
+	omap_writel(1, OMAP_IH1_CONTROL);
+}
+
+#endif	/* PM */
 
 /*
  * Allows tuning the IRQ type and priority
@@ -184,12 +217,17 @@ void __init omap_init_irq(void)
 	if (cpu_is_omap730()) {
 		irq_banks = omap730_irq_banks;
 		irq_bank_count = ARRAY_SIZE(omap730_irq_banks);
+
+		omap_wake_irq(INT_730_IH2_IRQ, 1);
+		omap_wake_irq(INT_730_WAKE_UP_REQ, 1);
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
 	if (cpu_is_omap1510()) {
 		irq_banks = omap1510_irq_banks;
 		irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
+
+		omap_wake_irq(INT_1510_IH2_IRQ, 1);
 	}
 	if (cpu_is_omap310()) {
 		irq_banks = omap310_irq_banks;
@@ -200,6 +238,9 @@ void __init omap_init_irq(void)
 	if (cpu_is_omap16xx()) {
 		irq_banks = omap1610_irq_banks;
 		irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
+
+		omap_wake_irq(INT_1610_IH2_IRQ, 1);
+		omap_wake_irq(INT_1610_WAKE_UP_REQ, 1);
 	}
 #endif
 	printk("Total of %i interrupts in %i interrupt banks\n",
Index: osk2/arch/arm/mach-omap1/pm.c
===================================================================
--- osk2.orig/arch/arm/mach-omap1/pm.c	2006-08-29 09:02:27.000000000 -0700
+++ osk2/arch/arm/mach-omap1/pm.c	2006-08-29 09:08:38.000000000 -0700
@@ -187,57 +187,8 @@ void omap_pm_idle(void)
 	local_irq_enable();
 }
 
-/*
- * Configuration of the wakeup event is board specific. For the
- * moment we put it into this helper function. Later it may move
- * to board specific files.
- */
-static void omap_pm_wakeup_setup(void)
-{
-	u32 level1_wake = 0;
-	u32 level2_wake = OMAP_IRQ_BIT(INT_UART2);
-
-	/*
-	 * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
-	 * and the L2 wakeup interrupts: keypad and UART2. Note that the
-	 * drivers must still separately call omap_set_gpio_wakeup() to
-	 * wake up to a GPIO interrupt.
-	 */
-	if (cpu_is_omap730())
-		level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) |
-			OMAP_IRQ_BIT(INT_730_IH2_IRQ);
-	else if (cpu_is_omap15xx())
-		level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
-			OMAP_IRQ_BIT(INT_1510_IH2_IRQ);
-	else if (cpu_is_omap16xx())
-		level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
-			OMAP_IRQ_BIT(INT_1610_IH2_IRQ);
-
-	omap_writel(~level1_wake, OMAP_IH1_MIR);
-
-	if (cpu_is_omap730()) {
-		omap_writel(~level2_wake, OMAP_IH2_0_MIR);
-		omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) |
-				OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)),
-				OMAP_IH2_1_MIR);
-	} else if (cpu_is_omap15xx()) {
-		level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
-		omap_writel(~level2_wake,  OMAP_IH2_MIR);
-	} else if (cpu_is_omap16xx()) {
-		level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
-		omap_writel(~level2_wake, OMAP_IH2_0_MIR);
-
-		/* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
-		omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ),
-			    OMAP_IH2_1_MIR);
-		omap_writel(~0x0, OMAP_IH2_2_MIR);
-		omap_writel(~0x0, OMAP_IH2_3_MIR);
-	}
+extern void omap_pm_wakeup_setup(void);
 
-	/*  New IRQ agreement, recalculate in cascade order */
-	omap_writel(1, OMAP_IH2_CONTROL);
-	omap_writel(1, OMAP_IH1_CONTROL);
-}
 
 #define EN_DSPCK	13	/* ARM_CKCTL */
 #define EN_APICK	6	/* ARM_IDLECT2 */

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



  reply	other threads:[~2006-08-30  8:22 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-08-15 17:03 [patch 2.6.17-rc4-omap-git] rtc-omap, rtc framework driver David Brownell
2006-08-15 17:25 ` Johnson, Steve-OMAP
2006-08-15 22:01   ` David Brownell
2006-08-15 22:03     ` Johnson, Steve-OMAP
2006-08-15 22:17       ` David Brownell
2006-08-16  3:12         ` Interrupts on Omap5912 OJ Ravadilla
2006-08-16  6:13           ` Arnold
2006-08-29 14:34         ` [patch 2.6.17-rc4-omap-git] rtc-omap, rtc framework driver Tony Lindgren
2006-08-29 19:51           ` David Brownell
2006-08-30  7:57             ` Tony Lindgren
2006-08-30  8:22               ` David Brownell [this message]
  -- strict thread matches above, loose matches on Subject: below --
2006-08-15 17:58 Woodruff, Richard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200608300122.14254.david-b@pacbell.net \
    --to=david-b@pacbell.net \
    --cc=linux-omap-open-source@linux.omap.com \
    --cc=tony@atomide.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.