All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv4 0/9] PRCM chain interrupt handling
@ 2011-06-29  9:04 Tero Kristo
  2011-06-29  9:04 ` [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism Tero Kristo
                   ` (8 more replies)
  0 siblings, 9 replies; 22+ messages in thread
From: Tero Kristo @ 2011-06-29  9:04 UTC (permalink / raw)
  To: linux-omap

Sorry for the delay, I had still some problems with the OMAP3 wakeup handling
with this set from suspend, but now this one works again. This set has been
tested on OMAP3 beagleboard, with suspend and cpuidle, with and without
off-mode. Appears to be working in all cases.

Main differences between previous version of the set:
- OMAP3 wakeup clearing moved back to PRCM interrupt (due to request)
  This caused problems with wakeup from suspend, and was fixed with patch #9
- PAD checks use now omap mux code
- PAD wakeups are enabled automatically by hwmod code for defined pads
- All other comments received for previous set should be taken care of
  (hopefully I didn't forget anything)

This patch set contains a number of testing purposes patches that should
probably not be integrated (tagged as TEMP.) They are mainly provided as
test setup for proof of consept.

-Tero


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism
  2011-06-29  9:04 [PATCHv4 0/9] PRCM chain interrupt handling Tero Kristo
@ 2011-06-29  9:04 ` Tero Kristo
  2011-06-29 16:53   ` Felipe Balbi
  2011-07-01 21:58   ` Kevin Hilman
  2011-06-29  9:04 ` [PATCHv4 2/9] PRCM: Add support for PAD wakeup interrupts Tero Kristo
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 22+ messages in thread
From: Tero Kristo @ 2011-06-29  9:04 UTC (permalink / raw)
  To: linux-omap
  Cc: Thomas Petazzoni, Avinash.H.M, Kevin Hilman, Cousson, Benoit,
	Tony Lindgren, Govindraj.R

Introduce a chained interrupt handler mechanism for the PRCM
interrupt, so that individual PRCM event can cleanly be handled by
handlers in separate drivers. We do this by introducing PRCM event
names, which are then matched to the particular PRCM interrupt bit
depending on the specific OMAP SoC being used.

arch/arm/mach-omap2/prcm.c implements the chained interrupt mechanism
itself, with individual PRCM events for OMAP3 and OMAP4 being
described in arch/arm/mach-omap2/prcm3xxx.c and
arch/arm/mach-omap2/prcm4xxx.c respectively. At initialization time,
the set of PRCM events is filtered against the SoC on which we are
running, keeping only the ones that are actually useful. All the logic
is written to be generic with regard to OMAP3/OMAP4, even though OMAP3
has single PRCM event registers and OMAP4 has two PRCM event
registers.

Patch tested on OMAP3 beagleboard.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Avinash.H.M <avinashhm@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
Cc: Cousson, Benoit <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Govindraj.R <govindraj.raja@ti.com>
---
 arch/arm/mach-omap2/Makefile           |    4 +
 arch/arm/mach-omap2/pm34xx.c           |  116 ++++++++--------------
 arch/arm/mach-omap2/prcm.c             |  163 ++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prcm3xxx.c         |  141 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/prcm4xxx.c         |  170 ++++++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/irqs.h |    9 ++-
 arch/arm/plat-omap/include/plat/prcm.h |   43 ++++++++
 7 files changed, 569 insertions(+), 77 deletions(-)
 create mode 100644 arch/arm/mach-omap2/prcm3xxx.c
 create mode 100644 arch/arm/mach-omap2/prcm4xxx.c

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 5024064..339d2d4 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -39,6 +39,10 @@ AFLAGS_sram242x.o			:=-Wa,-march=armv6
 AFLAGS_sram243x.o			:=-Wa,-march=armv6
 AFLAGS_sram34xx.o			:=-Wa,-march=armv7-a
 
+# PRCM
+obj-$(CONFIG_ARCH_OMAP3)                += prcm3xxx.o
+obj-$(CONFIG_ARCH_OMAP4)                += prcm4xxx.o
+
 # Pin multiplexing
 obj-$(CONFIG_SOC_OMAP2420)		+= mux2420.o
 obj-$(CONFIG_SOC_OMAP2430)		+= mux2430.o
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 96a7624..89cf027 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -64,6 +64,9 @@ static inline bool is_suspending(void)
 }
 #endif
 
+static int prcm_io_irq;
+static int prcm_wkup_irq;
+
 /* Scratchpad offsets */
 #define OMAP343X_TABLE_ADDRESS_OFFSET	   0xc4
 #define OMAP343X_TABLE_VALUE_OFFSET	   0xc0
@@ -240,75 +243,16 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs)
 	return c;
 }
 
-static int _prcm_int_handle_wakeup(void)
+static irqreturn_t _prcm_int_handle_wakeup(int irq, void *unused)
 {
-	int c;
-
-	c = prcm_clear_mod_irqs(WKUP_MOD, 1);
-	c += prcm_clear_mod_irqs(CORE_MOD, 1);
-	c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1);
+	prcm_clear_mod_irqs(WKUP_MOD, 1);
+	prcm_clear_mod_irqs(CORE_MOD, 1);
+	prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1);
 	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		c += prcm_clear_mod_irqs(CORE_MOD, 3);
-		c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1);
+		prcm_clear_mod_irqs(CORE_MOD, 3);
+		prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1);
 	}
 
-	return c;
-}
-
-/*
- * PRCM Interrupt Handler
- *
- * The PRM_IRQSTATUS_MPU register indicates if there are any pending
- * interrupts from the PRCM for the MPU. These bits must be cleared in
- * order to clear the PRCM interrupt. The PRCM interrupt handler is
- * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear
- * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU
- * register indicates that a wake-up event is pending for the MPU and
- * this bit can only be cleared if the all the wake-up events latched
- * in the various PM_WKST_x registers have been cleared. The interrupt
- * handler is implemented using a do-while loop so that if a wake-up
- * event occurred during the processing of the prcm interrupt handler
- * (setting a bit in the corresponding PM_WKST_x register and thus
- * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register)
- * this would be handled.
- */
-static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
-{
-	u32 irqenable_mpu, irqstatus_mpu;
-	int c = 0;
-
-	irqenable_mpu = omap2_prm_read_mod_reg(OCP_MOD,
-					 OMAP3_PRM_IRQENABLE_MPU_OFFSET);
-	irqstatus_mpu = omap2_prm_read_mod_reg(OCP_MOD,
-					 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-	irqstatus_mpu &= irqenable_mpu;
-
-	do {
-		if (irqstatus_mpu & (OMAP3430_WKUP_ST_MASK |
-				     OMAP3430_IO_ST_MASK)) {
-			c = _prcm_int_handle_wakeup();
-
-			/*
-			 * Is the MPU PRCM interrupt handler racing with the
-			 * IVA2 PRCM interrupt handler ?
-			 */
-			WARN(c == 0, "prcm: WARNING: PRCM indicated MPU wakeup "
-			     "but no wakeup sources are marked\n");
-		} else {
-			/* XXX we need to expand our PRCM interrupt handler */
-			WARN(1, "prcm: WARNING: PRCM interrupt received, but "
-			     "no code to handle it (%08x)\n", irqstatus_mpu);
-		}
-
-		omap2_prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
-					OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-
-		irqstatus_mpu = omap2_prm_read_mod_reg(OCP_MOD,
-					OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-		irqstatus_mpu &= irqenable_mpu;
-
-	} while (irqstatus_mpu);
-
 	return IRQ_HANDLED;
 }
 
@@ -880,20 +824,35 @@ static int __init omap3_pm_init(void)
 	/* XXX prcm_setup_regs needs to be before enabling hw
 	 * supervised mode for powerdomains */
 	prcm_setup_regs();
+	ret = omap_prcm_irq_init();
+	if (ret) {
+		pr_err("omap_prcm_irq_init() failed with %d\n", ret);
+		goto err_prcm_irq_init;
+	}
+
+	prcm_wkup_irq = omap_prcm_event_to_irq("wkup");
+	prcm_io_irq = omap_prcm_event_to_irq("io");
+
+	ret = request_irq(prcm_wkup_irq, _prcm_int_handle_wakeup,
+			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_wkup", NULL);
 
-	ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
-			  (irq_handler_t)prcm_interrupt_handler,
-			  IRQF_DISABLED, "prcm", NULL);
 	if (ret) {
-		printk(KERN_ERR "request_irq failed to register for 0x%x\n",
-		       INT_34XX_PRCM_MPU_IRQ);
-		goto err1;
+		printk(KERN_ERR "Failed to request prcm_wkup irq\n");
+		goto err_prcm_wkup;
+	}
+
+	ret = request_irq(prcm_io_irq, _prcm_int_handle_wakeup,
+			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_io", NULL);
+
+	if (ret) {
+		printk(KERN_ERR "Failed to request prcm_io irq\n");
+		goto err_prcm_io;
 	}
 
 	ret = pwrdm_for_each(pwrdms_setup, NULL);
 	if (ret) {
 		printk(KERN_ERR "Failed to setup powerdomains\n");
-		goto err2;
+		goto err_pwrdms_setup;
 	}
 
 	(void) clkdm_for_each(clkdms_setup, NULL);
@@ -901,7 +860,7 @@ static int __init omap3_pm_init(void)
 	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
 	if (mpu_pwrdm == NULL) {
 		printk(KERN_ERR "Failed to get mpu_pwrdm\n");
-		goto err2;
+		goto err_pwrdms_setup;
 	}
 
 	neon_pwrdm = pwrdm_lookup("neon_pwrdm");
@@ -950,14 +909,19 @@ static int __init omap3_pm_init(void)
 	}
 
 	omap3_save_scratchpad_contents();
-err1:
+
 	return ret;
-err2:
-	free_irq(INT_34XX_PRCM_MPU_IRQ, NULL);
+
+ err_pwrdms_setup:
 	list_for_each_entry_safe(pwrst, tmp, &pwrst_list, node) {
 		list_del(&pwrst->node);
 		kfree(pwrst);
 	}
+ err_prcm_io:
+	free_irq(prcm_wkup_irq, NULL);
+ err_prcm_wkup:
+	omap_prcm_irq_cleanup();
+ err_prcm_irq_init:
 	return ret;
 }
 
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 6be1438..794e451 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -23,6 +23,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
 
 #include <mach/system.h>
 #include <plat/common.h>
@@ -45,6 +47,167 @@ void __iomem *cm2_base;
 
 #define MAX_MODULE_ENABLE_WAIT		100000
 
+/* Setup for the interrupt handling based on used platform */
+static struct omap_prcm_irq_setup *irq_setup;
+
+static void prcm_irq_ack(struct irq_data *data)
+{
+	unsigned int prcm_irq = data->irq - OMAP_PRCM_IRQ_BASE;
+	irq_setup->ack_event(prcm_irq);
+}
+
+static void prcm_irq_mask(struct irq_data *data)
+{
+	unsigned int prcm_irq = data->irq - OMAP_PRCM_IRQ_BASE;
+	irq_setup->mask_event(prcm_irq);
+}
+
+static void prcm_irq_unmask(struct irq_data *data)
+{
+	unsigned int prcm_irq = data->irq - OMAP_PRCM_IRQ_BASE;
+	irq_setup->unmask_event(prcm_irq);
+}
+
+static struct irq_chip_generic *prcm_irq_chips[OMAP_PRCM_MAX_NR_PENDING_REG];
+
+/*
+ * PRCM Interrupt Handler
+ *
+ * The PRM_IRQSTATUS_MPU register indicates if there are any pending
+ * interrupts from the PRCM for the MPU. These bits must be cleared in
+ * order to clear the PRCM interrupt. The PRCM interrupt handler is
+ * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear
+ * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU
+ * register indicates that a wake-up event is pending for the MPU and
+ * this bit can only be cleared if the all the wake-up events latched
+ * in the various PM_WKST_x registers have been cleared. The interrupt
+ * handler is implemented using a do-while loop so that if a wake-up
+ * event occurred during the processing of the prcm interrupt handler
+ * (setting a bit in the corresponding PM_WKST_x register and thus
+ * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register)
+ * this would be handled.
+ */
+static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG];
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	/*
+	 * Loop until all pending irqs are handled, since
+	 * generic_handle_irq(), called by prcm_irq_handle_virtirqs()
+	 * can cause new irqs to come
+	 */
+	while (1) {
+		unsigned int virtirq;
+
+		chip->irq_ack(&desc->irq_data);
+
+		memset(pending, 0, sizeof(pending));
+		irq_setup->pending_events(pending);
+
+		/* No bit set, then all IRQs are handled */
+		if (find_first_bit(pending, OMAP_PRCM_NR_IRQS)
+		    >= OMAP_PRCM_NR_IRQS) {
+			chip->irq_unmask(&desc->irq_data);
+			break;
+		}
+
+		/*
+		 * Loop on all currently pending irqs so that new irqs
+		 * cannot starve previously pending irqs
+		 */
+		for_each_set_bit(virtirq, pending, OMAP_PRCM_NR_IRQS)
+			generic_handle_irq(OMAP_PRCM_IRQ_BASE + virtirq);
+
+		chip->irq_unmask(&desc->irq_data);
+	}
+}
+
+/*
+ * Given a PRCM event name, returns the corresponding IRQ on which the
+ * handler should be registered.
+ */
+int omap_prcm_event_to_irq(const char *name)
+{
+	int i;
+
+	for (i = 0; i < irq_setup->num_irqs; i++)
+		if (!strcmp(irq_setup->irqs[i].name, name))
+			return OMAP_PRCM_IRQ_BASE + irq_setup->irqs[i].offset;
+
+	return -ENOENT;
+}
+
+/*
+ * Prepare the array of PRCM events corresponding to the current SoC,
+ * and set-up the chained interrupt handler mechanism.
+ */
+int __init omap_prcm_irq_init(void)
+{
+	int i;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	u32 mask[2] = { 0, 0 };
+	int offset;
+	int max_irq = 0;
+
+	for (i = 0; i < irq_setup->num_irqs; i++)
+		if (omap_chip_is(irq_setup->irqs[i].omap_chip)) {
+			offset = irq_setup->irqs[i].offset;
+			if (offset < 32)
+				mask[0] |= 1 << offset;
+			else
+				mask[1] |= 1 << (offset - 32);
+			if (offset > max_irq)
+				max_irq = offset;
+		}
+
+	irq_set_chained_handler(irq_setup->irq, prcm_irq_handler);
+
+	for (i = 0; i <= max_irq / 32; i++) {
+		gc = irq_alloc_generic_chip("PRCM", 1,
+			OMAP_PRCM_IRQ_BASE + i * 32, NULL, handle_level_irq);
+
+		ct = gc->chip_types;
+		ct->chip.irq_ack = prcm_irq_ack;
+		ct->chip.irq_mask = prcm_irq_mask;
+		ct->chip.irq_unmask = prcm_irq_unmask;
+
+		irq_setup_generic_chip(gc, mask[i], 0, IRQ_NOREQUEST, 0);
+		prcm_irq_chips[i] = gc;
+	}
+	return 0;
+}
+
+/*
+ * Reverses memory allocated and other setups done by
+ * omap_prcm_irq_init().
+ */
+void omap_prcm_irq_cleanup(void)
+{
+	int i;
+
+	for (i = 0; i < OMAP_PRCM_MAX_NR_PENDING_REG; i++)
+		irq_remove_generic_chip(prcm_irq_chips[i], 0xffffffff, 0, 0);
+
+	irq_set_chained_handler(irq_setup->irq, NULL);
+}
+
+void __init omap_prcm_irq_setup(struct omap_prcm_irq_setup *setup)
+{
+	struct omap_prcm_irq *irqs;
+
+	/* Copy setup from __initdata section */
+	irq_setup = kmalloc(sizeof(struct omap_prcm_irq_setup), GFP_KERNEL);
+	memcpy(irq_setup, setup, sizeof(struct omap_prcm_irq_setup));
+
+	irqs = kmalloc(sizeof(struct omap_prcm_irq) *
+		setup->num_irqs, GFP_KERNEL);
+	memcpy(irqs, setup->irqs, sizeof(struct omap_prcm_irq) *
+		setup->num_irqs);
+	irq_setup->irqs = irqs;
+}
+
 u32 omap_prcm_get_reset_sources(void)
 {
 	/* XXX This presumably needs modification for 34XX */
diff --git a/arch/arm/mach-omap2/prcm3xxx.c b/arch/arm/mach-omap2/prcm3xxx.c
new file mode 100644
index 0000000..5671650
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm3xxx.c
@@ -0,0 +1,141 @@
+/*
+ * linux/arch/arm/mach-omap2/prcm3xxx.c
+ *
+ * OMAP 3xxx Power Reset and Clock Management (PRCM) interrupt
+ * definitions
+ *
+ * Written by Thomas Petazzoni <t-petazzoni@ti.com>
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+
+#include <plat/prcm.h>
+#include <plat/cpu.h>
+#include <plat/irqs.h>
+
+#include "prm-regbits-24xx.h"
+
+static void omap3_prcm_mask_event(unsigned event);
+static void omap3_prcm_unmask_event(unsigned event);
+static void omap3_prcm_ack_event(unsigned event);
+static void omap3_prcm_pending_events(unsigned long *events);
+
+static struct omap_prcm_irq  __initdata omap_prcm_3xxx_irqs[] = {
+	OMAP_PRCM_IRQ("wkup",                  0,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("evgenon",               2,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("evgenoff",              3,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("transition",            4,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("core_dpll_recal",       5,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("periph_dpll_recal",     6,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("mpu_dpll_recal",        7,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("iva2_dpll_recal",       8,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("io",	            9,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp1_oppchangedone",    10,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp1_minvdd",           11,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp1_maxvdd",           12,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp1_nosmpsack",        13,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp1_eqvalue",          14,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp1_tranxdone",        15,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp2_oppchangedone",    16,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp2_minvdd",           17,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp2_maxvdd",           18,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp2_nosmpsack",        19,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp2_eqvalue",          20,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vp2_tranxdone",        21,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vc_saerr",             22,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vc_raerr",             23,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vc_timeout_err",       24,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("snd_periph_recal",     25,
+		      CHIP_IS_OMAP3430 | CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("abb_ldo_tranxdone",    26,
+		      CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vc_vp1_ack",           27,
+		      CHIP_GE_OMAP3630ES1_1),
+	OMAP_PRCM_IRQ("vc_bypass_ack",        28,
+		      CHIP_GE_OMAP3630ES1_1),
+};
+
+static struct omap_prcm_irq_setup __initdata omap3_prcm_irq_setup = {
+	.mask_event = omap3_prcm_mask_event,
+	.unmask_event = omap3_prcm_unmask_event,
+	.ack_event = omap3_prcm_ack_event,
+	.pending_events = omap3_prcm_pending_events,
+	.irqs = omap_prcm_3xxx_irqs,
+	.num_irqs = ARRAY_SIZE(omap_prcm_3xxx_irqs),
+	.irq = INT_34XX_PRCM_MPU_IRQ,
+};
+
+static void omap3_prcm_mask_event(unsigned event)
+{
+	unsigned int bit = BIT(event);
+
+	omap2_prm_rmw_mod_reg_bits(bit, 0, OCP_MOD,
+				   OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+}
+
+static void omap3_prcm_unmask_event(unsigned event)
+{
+	unsigned int bit = BIT(event);
+
+	omap2_prm_rmw_mod_reg_bits(0, bit, OCP_MOD,
+				   OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+}
+
+static void omap3_prcm_ack_event(unsigned event)
+{
+	unsigned int bit = BIT(event);
+
+	omap2_prm_write_mod_reg(bit, OCP_MOD,
+				OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+}
+
+static void omap3_prcm_pending_events(unsigned long *events)
+{
+	u32 irqenable_mpu =
+		omap2_prm_read_mod_reg(OCP_MOD,
+				       OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+	u32 irqstatus_mpu =
+		omap2_prm_read_mod_reg(OCP_MOD,
+				       OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	events[0] = irqenable_mpu & irqstatus_mpu;
+}
+
+static int __init omap3_prcm_setup_irq(void)
+{
+	if (!cpu_is_omap34xx())
+		return -ENODEV;
+	omap_prcm_irq_setup(&omap3_prcm_irq_setup);
+	return 0;
+}
+arch_initcall(omap3_prcm_setup_irq);
diff --git a/arch/arm/mach-omap2/prcm4xxx.c b/arch/arm/mach-omap2/prcm4xxx.c
new file mode 100644
index 0000000..e4d267e
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm4xxx.c
@@ -0,0 +1,170 @@
+/*
+ * linux/arch/arm/mach-omap2/prcm4xxx.c
+ *
+ * OMAP 4xxx Power Reset and Clock Management (PRCM) interrupt
+ * definitions
+ *
+ * Written by Thomas Petazzoni <t-petazzoni@ti.com>
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+
+#include <plat/prcm.h>
+#include <plat/cpu.h>
+#include <plat/irqs.h>
+
+#include "prcm44xx.h"
+#include "prm44xx.h"
+
+static void omap4_prcm_mask_event(unsigned event);
+static void omap4_prcm_unmask_event(unsigned event);
+static void omap4_prcm_ack_event(unsigned event);
+static void omap4_prcm_pending_events(unsigned long *events);
+
+struct omap_prcm_irq __initdata omap_prcm_4xxx_irqs[] = {
+	OMAP_PRCM_IRQ("dpll_core_recal",       0,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("dpll_mpu_recal",        1,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("dpll_iva_recal",        2,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("dpll_per_recal",        3,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("dpll_abe_recal",        4,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("dpll_usb_recal",        5,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("dpll_unipro_recal",     7,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("transition",            8,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("io",                    9,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vc_saerr",              11,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vc_raerr",              12,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vc_toerr",              13,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vc_bypassack",          14,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_core_oppchangedone", 16,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_core_minvdd",        17,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_core_maxvdd",        18,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_core_nosmpsack",     19,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_core_eqvalue",       20,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_core_tranxdone",     21,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_iva_oppchangedone",  24,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_iva_minvdd",         25,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_iva_maxvdd",         26,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_iva_nosmpsack",      27,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_iva_eqvalue",        28,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_iva_tranxdone",      29,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_iva_vpack",          30,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("abb_iva_done",          31,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_mpu_oppchangedone",  32,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_mpu_minvdd",         33,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_mpu_maxvdd",         34,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_mpu_nosmpsack",      35,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_mpu_eqvalue",        36,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_mpu_tranxdone",      37,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("vp_mpu_vpack",          38,
+		      CHIP_IS_OMAP4430),
+	OMAP_PRCM_IRQ("abb_mpu_done",          39,
+		      CHIP_IS_OMAP4430),
+};
+
+static struct omap_prcm_irq_setup __initdata omap4_prcm_irq_setup = {
+	.mask_event = omap4_prcm_mask_event,
+	.unmask_event = omap4_prcm_unmask_event,
+	.ack_event = omap4_prcm_ack_event,
+	.pending_events = omap4_prcm_pending_events,
+	.irqs = omap_prcm_4xxx_irqs,
+	.num_irqs = ARRAY_SIZE(omap_prcm_4xxx_irqs),
+	.irq = OMAP44XX_IRQ_PRCM,
+};
+
+void omap4_prcm_mask_event(unsigned event)
+{
+	unsigned int bit = BIT(event % 32);
+	unsigned int off = (event / 32) * 4;
+
+	omap4_prm_rmw_inst_reg_bits(bit, 0,
+				    OMAP4430_PRM_OCP_SOCKET_INST,
+				    OMAP4_PRM_IRQENABLE_MPU_OFFSET + off);
+}
+
+void omap4_prcm_unmask_event(unsigned event)
+{
+	unsigned int bit = BIT(event % 32);
+	unsigned int off = (event / 32) * 4;
+
+	omap4_prm_rmw_inst_reg_bits(0, bit,
+				    OMAP4430_PRM_OCP_SOCKET_INST,
+				    OMAP4_PRM_IRQENABLE_MPU_OFFSET + off);
+}
+
+void omap4_prcm_ack_event(unsigned event)
+{
+	unsigned int bit = BIT(event % 32);
+	unsigned int off = (event / 32) * 4;
+
+	omap4_prm_write_inst_reg(bit,
+				 OMAP4430_PRM_OCP_SOCKET_INST,
+				 OMAP4_PRM_IRQSTATUS_MPU_OFFSET + off);
+}
+
+void omap4_prcm_pending_events(unsigned long *events)
+{
+	u32 irqenable_mpu, irqstatus_mpu;
+	int i;
+
+	/* OMAP4 has two enable/status registers for the PRCM */
+	for (i = 0; i < 2; i++) {
+		irqenable_mpu =
+			omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+						OMAP4_PRM_IRQENABLE_MPU_OFFSET
+						+ i * 4);
+		irqstatus_mpu =
+			omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+						OMAP4_PRM_IRQSTATUS_MPU_OFFSET
+						+ i * 4);
+		events[i] = irqenable_mpu & irqstatus_mpu;
+	}
+}
+
+int __init omap4_prcm_setup_irq(void)
+{
+	if (!cpu_is_omap44xx())
+		return -ENODEV;
+	omap_prcm_irq_setup(&omap4_prcm_irq_setup);
+	return 0;
+}
+arch_initcall(omap4_prcm_setup_irq);
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index 5a25098..23b9680 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -366,7 +366,14 @@
 #define OMAP_MAX_GPIO_LINES	192
 #define IH_GPIO_BASE		(128 + IH2_BASE)
 #define IH_MPUIO_BASE		(OMAP_MAX_GPIO_LINES + IH_GPIO_BASE)
-#define OMAP_IRQ_END		(IH_MPUIO_BASE + 16)
+#define OMAP_MPUIO_IRQ_END	(IH_MPUIO_BASE + 16)
+
+/* 64 IRQs for the PRCM (32 are needed on OMAP3, 64 on OMAP4) */
+#define OMAP_PRCM_IRQ_BASE      (OMAP_MPUIO_IRQ_END)
+#define OMAP_PRCM_NR_IRQS       64
+#define OMAP_PRCM_IRQ_END       (OMAP_PRCM_IRQ_BASE + OMAP_PRCM_NR_IRQS)
+
+#define OMAP_IRQ_END            (OMAP_PRCM_IRQ_END)
 
 /* External FPGA handles interrupts on Innovator boards */
 #define	OMAP_FPGA_IRQ_BASE	(OMAP_IRQ_END)
diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
index 267f43b..205b9b1 100644
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ b/arch/arm/plat-omap/include/plat/prcm.h
@@ -27,6 +27,49 @@
 #ifndef __ASM_ARM_ARCH_OMAP_PRCM_H
 #define __ASM_ARM_ARCH_OMAP_PRCM_H
 
+#include <plat/cpu.h>
+
+/*
+ * Structure describing the interrupt corresponding to each PRCM event
+ */
+struct omap_prcm_irq {
+	/* Logical name for the interrupt */
+	const char *name;
+
+	/*
+	 * Corresponding offset in the status/enable register. The
+	 * offset can be greater than 32, in which case it spans over
+	 * the second status register
+	 */
+	unsigned int offset;
+
+	/* OMAP chip for which this PRCM event exists */
+	const struct omap_chip_id omap_chip;
+};
+
+#define OMAP_PRCM_IRQ(_name, _offset, _chip)   \
+	{ .name = _name,                       \
+	  .offset = _offset,                   \
+	  .omap_chip = OMAP_CHIP_INIT(_chip) }
+
+/* Maximum number of PRCM interrupt status registers */
+#define OMAP_PRCM_MAX_NR_PENDING_REG 2
+
+/* Setup for the PRCM interrupt handler */
+struct omap_prcm_irq_setup {
+	void (*mask_event)(unsigned);
+	void (*unmask_event)(unsigned);
+	void (*ack_event)(unsigned);
+	void (*pending_events)(unsigned long *);
+	struct omap_prcm_irq *irqs;
+	int num_irqs;
+	int irq;
+};
+
+int omap_prcm_event_to_irq(const char *name);
+int omap_prcm_irq_init(void);
+void omap_prcm_irq_setup(struct omap_prcm_irq_setup *setup);
+void omap_prcm_irq_cleanup(void);
 u32 omap_prcm_get_reset_sources(void);
 int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
 			 const char *name);
-- 
1.7.4.1


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCHv4 2/9] PRCM: Add support for PAD wakeup interrupts
  2011-06-29  9:04 [PATCHv4 0/9] PRCM chain interrupt handling Tero Kristo
  2011-06-29  9:04 ` [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism Tero Kristo
@ 2011-06-29  9:04 ` Tero Kristo
  2011-06-30 17:10   ` Govindraj
  2011-07-01 22:03   ` Kevin Hilman
  2011-06-29  9:04 ` [PATCHv4 3/9] OMAP3: PM: remove serial resume / idle calls from idle path Tero Kristo
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 22+ messages in thread
From: Tero Kristo @ 2011-06-29  9:04 UTC (permalink / raw)
  To: linux-omap

PRCM interrupt handler will now parse registered pads to see whether there
is an active wakeup event. If there is a pending wakeup event, the registered
ISR will be called.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/prcm.c             |   94 ++++++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/prcm.h |    5 ++
 2 files changed, 99 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 794e451..6b603eb 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -30,6 +30,7 @@
 #include <plat/common.h>
 #include <plat/prcm.h>
 #include <plat/irqs.h>
+#include <plat/omap_hwmod.h>
 
 #include "clock.h"
 #include "clock2xxx.h"
@@ -40,6 +41,7 @@
 #include "prm-regbits-24xx.h"
 #include "prm-regbits-44xx.h"
 #include "control.h"
+#include "mux.h"
 
 void __iomem *prm_base;
 void __iomem *cm_base;
@@ -50,6 +52,15 @@ void __iomem *cm2_base;
 /* Setup for the interrupt handling based on used platform */
 static struct omap_prcm_irq_setup *irq_setup;
 
+/* PAD handlers list */
+struct pad_def {
+	struct omap_device_pad *pad;
+	unsigned int irq;
+	struct list_head node;
+};
+
+static LIST_HEAD(pad_handler_list);
+
 static void prcm_irq_ack(struct irq_data *data)
 {
 	unsigned int prcm_irq = data->irq - OMAP_PRCM_IRQ_BASE;
@@ -71,6 +82,24 @@ static void prcm_irq_unmask(struct irq_data *data)
 static struct irq_chip_generic *prcm_irq_chips[OMAP_PRCM_MAX_NR_PENDING_REG];
 
 /*
+ * Handler for PAD irqs, called from PRCM interrupt handler
+ */
+static void omap_prcm_handle_pad_irqs(void)
+{
+	struct pad_def *def;
+	u16 val = 0;
+	list_for_each_entry(def, &pad_handler_list, node) {
+		/* Read padconf value */
+		val = omap_mux_read(def->pad->partition,
+			def->pad->mux->reg_offset);
+
+		/* If pad wakeupevent is active, call registered ISR */
+		if (val & OMAP3_PADCONF_WAKEUPEVENT0)
+			generic_handle_irq(def->irq);
+	}
+}
+
+/*
  * PRCM Interrupt Handler
  *
  * The PRM_IRQSTATUS_MPU register indicates if there are any pending
@@ -92,6 +121,9 @@ static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
 	unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG];
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 
+	/* Handle PAD events first, we don't want to ack them before parse */
+	omap_prcm_handle_pad_irqs();
+
 	/*
 	 * Loop until all pending irqs are handled, since
 	 * generic_handle_irq(), called by prcm_irq_handle_virtirqs()
@@ -139,6 +171,68 @@ int omap_prcm_event_to_irq(const char *name)
 }
 
 /*
+ * Register interrupt handler for a given omap_hwmod_mux. When the PRCM
+ * interrupt handler detects wakeupevent on the corresponding pad, the
+ * ISR will be called.
+ */
+int omap_prcm_register_pad_irqs(struct omap_hwmod_mux_info *mux,
+				unsigned int irq)
+{
+	struct pad_def *def;
+	int i;
+	u16 val;
+
+	if (!mux)
+		return 0;
+
+	for (i = 0; i < mux->nr_pads; i++) {
+		if (!(mux->pads[i].enable & OMAP_PIN_INPUT))
+			continue;
+
+		def = kmalloc(sizeof(struct pad_def), GFP_ATOMIC);
+		if (!def)
+			return -ENOMEM;
+
+		def->pad = mux->pads + i;
+		def->irq = irq;
+
+		/* Enable pad wakeup */
+		val = omap_mux_read(def->pad->partition,
+			def->pad->mux->reg_offset);
+		val |= OMAP_WAKEUP_EN;
+		omap_mux_write(def->pad->partition, val,
+			def->pad->mux->reg_offset);
+
+		list_add(&def->node, &pad_handler_list);
+	}
+	return 0;
+}
+
+/*
+ * Unregister pad irqs associated with a hwmod mux
+ */
+void omap_prcm_unregister_pad_irqs(struct omap_hwmod_mux_info *mux)
+{
+	struct pad_def *def;
+	int i;
+	u16 val;
+
+	list_for_each_entry(def, &pad_handler_list, node)
+		for (i = 0; i < mux->nr_pads; i++)
+			if (def->pad == mux->pads + i) {
+				list_del(&def->node);
+
+				/* Disable pad wakeup */
+				val = omap_mux_read(def->pad->partition,
+					def->pad->mux->reg_offset);
+				val &= ~OMAP_WAKEUP_EN;
+				omap_mux_write(def->pad->partition, val,
+					def->pad->mux->reg_offset);
+				kfree(def);
+			}
+}
+
+/*
  * Prepare the array of PRCM events corresponding to the current SoC,
  * and set-up the chained interrupt handler mechanism.
  */
diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
index 205b9b1..7987819 100644
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ b/arch/arm/plat-omap/include/plat/prcm.h
@@ -66,10 +66,15 @@ struct omap_prcm_irq_setup {
 	int irq;
 };
 
+struct omap_hwmod_mux_info;
+
 int omap_prcm_event_to_irq(const char *name);
 int omap_prcm_irq_init(void);
 void omap_prcm_irq_setup(struct omap_prcm_irq_setup *setup);
 void omap_prcm_irq_cleanup(void);
+int omap_prcm_register_pad_irqs(struct omap_hwmod_mux_info *mux,
+				unsigned int irq);
+void omap_prcm_unregister_pad_irqs(struct omap_hwmod_mux_info *mux);
 u32 omap_prcm_get_reset_sources(void);
 int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
 			 const char *name);
-- 
1.7.4.1


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCHv4 3/9] OMAP3: PM: remove serial resume / idle calls from idle path
  2011-06-29  9:04 [PATCHv4 0/9] PRCM chain interrupt handling Tero Kristo
  2011-06-29  9:04 ` [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism Tero Kristo
  2011-06-29  9:04 ` [PATCHv4 2/9] PRCM: Add support for PAD wakeup interrupts Tero Kristo
@ 2011-06-29  9:04 ` Tero Kristo
  2011-06-30 16:50   ` Govindraj
  2011-06-29  9:04 ` [PATCHv4 4/9] TEMP: OMAP3: Serial: Made serial to work properly with PRCM chain handler Tero Kristo
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Tero Kristo @ 2011-06-29  9:04 UTC (permalink / raw)
  To: linux-omap

This is no longer needed as it will be handled within serial driver itself.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/pm34xx.c |   19 -------------------
 1 files changed, 0 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 89cf027..e626a3d 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -335,18 +335,9 @@ void omap_sram_idle(void)
 		omap3_enable_io_chain();
 	}
 
-	/* Block console output in case it is on one of the OMAP UARTs */
-	if (!is_suspending())
-		if (per_next_state < PWRDM_POWER_ON ||
-		    core_next_state < PWRDM_POWER_ON)
-			if (!console_trylock())
-				goto console_still_active;
-
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
-		omap_uart_prepare_idle(2);
-		omap_uart_prepare_idle(3);
 		omap2_gpio_prepare_for_idle(per_going_off);
 		if (per_next_state == PWRDM_POWER_OFF)
 				omap3_per_save_context();
@@ -354,8 +345,6 @@ void omap_sram_idle(void)
 
 	/* CORE */
 	if (core_next_state < PWRDM_POWER_ON) {
-		omap_uart_prepare_idle(0);
-		omap_uart_prepare_idle(1);
 		if (core_next_state == PWRDM_POWER_OFF) {
 			omap3_core_save_context();
 			omap3_cm_save_context();
@@ -402,8 +391,6 @@ void omap_sram_idle(void)
 			omap3_sram_restore_context();
 			omap2_sms_restore_context();
 		}
-		omap_uart_resume_idle(0);
-		omap_uart_resume_idle(1);
 		if (core_next_state == PWRDM_POWER_OFF)
 			omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
 					       OMAP3430_GR_MOD,
@@ -417,14 +404,8 @@ void omap_sram_idle(void)
 		omap2_gpio_resume_after_idle();
 		if (per_prev_state == PWRDM_POWER_OFF)
 			omap3_per_restore_context();
-		omap_uart_resume_idle(2);
-		omap_uart_resume_idle(3);
 	}
 
-	if (!is_suspending())
-		console_unlock();
-
-console_still_active:
 	/* Disable IO-PAD and IO-CHAIN wakeup */
 	if (omap3_has_io_wakeup() &&
 	    (per_next_state < PWRDM_POWER_ON ||
-- 
1.7.4.1


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCHv4 4/9] TEMP: OMAP3: Serial: Made serial to work properly with PRCM chain handler
  2011-06-29  9:04 [PATCHv4 0/9] PRCM chain interrupt handling Tero Kristo
                   ` (2 preceding siblings ...)
  2011-06-29  9:04 ` [PATCHv4 3/9] OMAP3: PM: remove serial resume / idle calls from idle path Tero Kristo
@ 2011-06-29  9:04 ` Tero Kristo
  2011-06-29  9:04 ` [PATCHv4 5/9] TEMP: Serial: Added mux support Tero Kristo
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Tero Kristo @ 2011-06-29  9:04 UTC (permalink / raw)
  To: linux-omap

This patch is just a temporary hack to allow serial to work properly with
the PRCM chain handler. Should be replaced with a proper implementation.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/serial.c     |   28 +++++++++-------------------
 drivers/tty/serial/omap-serial.c |    8 ++++++++
 2 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 1ac361b..067a86b 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -39,6 +39,7 @@
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
+#include <plat/prcm.h>
 
 #include "prm2xxx_3xxx.h"
 #include "pm.h"
@@ -380,6 +381,7 @@ static void omap_uart_allow_sleep(struct omap_uart_state *uart)
 	omap_uart_smart_idle_enable(uart, 1);
 	uart->can_sleep = 1;
 	del_timer(&uart->timer);
+	omap_uart_disable_clocks(uart);
 }
 
 static void omap_uart_idle_timer(unsigned long data)
@@ -391,35 +393,23 @@ static void omap_uart_idle_timer(unsigned long data)
 
 void omap_uart_prepare_idle(int num)
 {
-	struct omap_uart_state *uart;
-
-	list_for_each_entry(uart, &uart_list, node) {
-		if (num == uart->num && uart->can_sleep) {
-			omap_uart_disable_clocks(uart);
-			return;
-		}
-	}
 }
 
 void omap_uart_resume_idle(int num)
 {
 	struct omap_uart_state *uart;
+	u32 wkst;
 
 	list_for_each_entry(uart, &uart_list, node) {
 		if (num == uart->num && uart->can_sleep) {
-			omap_uart_enable_clocks(uart);
+			omap_uart_block_sleep(uart);
 
-			/* Check for IO pad wakeup */
-			if (cpu_is_omap34xx() && uart->padconf) {
-				u16 p = omap_ctrl_readw(uart->padconf);
-
-				if (p & OMAP3_PADCONF_WAKEUPEVENT0)
-					omap_uart_block_sleep(uart);
+			/* Check for normal UART wakeup (and clear it) */
+			if (uart->wk_st && uart->wk_mask) {
+				wkst = __raw_readl(uart->wk_st) & uart->wk_mask;
+				if (wkst)
+					__raw_writel(wkst, uart->wk_st);
 			}
-
-			/* Check for normal UART wakeup */
-			if (__raw_readl(uart->wk_st) & uart->wk_mask)
-				omap_uart_block_sleep(uart);
 			return;
 		}
 	}
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 47cadf4..bd6ae02 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -261,6 +261,8 @@ static void serial_omap_start_tx(struct uart_port *port)
 	unsigned int start;
 	int ret = 0;
 
+	omap_uart_resume_idle(up->pdev->id);
+
 	if (!up->use_dma) {
 		serial_omap_enable_ier_thri(up);
 		return;
@@ -354,6 +356,8 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
 	unsigned int iir, lsr;
 	unsigned long flags;
 
+	omap_uart_resume_idle(up->pdev->id);
+
 	iir = serial_in(up, UART_IIR);
 	if (iir & UART_IIR_NO_INT)
 		return IRQ_NONE;
@@ -641,6 +645,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	unsigned long flags = 0;
 	unsigned int baud, quot;
 
+	omap_uart_resume_idle(up->pdev->id);
+
 	switch (termios->c_cflag & CSIZE) {
 	case CS5:
 		cval = UART_LCR_WLEN5;
@@ -947,6 +953,8 @@ serial_omap_console_write(struct console *co, const char *s,
 	unsigned int ier;
 	int locked = 1;
 
+	omap_uart_resume_idle(up->pdev->id);
+
 	local_irq_save(flags);
 	if (up->port.sysrq)
 		locked = 0;
-- 
1.7.4.1


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCHv4 5/9] TEMP: Serial: Added mux support
  2011-06-29  9:04 [PATCHv4 0/9] PRCM chain interrupt handling Tero Kristo
                   ` (3 preceding siblings ...)
  2011-06-29  9:04 ` [PATCHv4 4/9] TEMP: OMAP3: Serial: Made serial to work properly with PRCM chain handler Tero Kristo
@ 2011-06-29  9:04 ` Tero Kristo
  2011-06-29  9:05 ` [PATCHv4 6/9] OMAP device: change pr_warnings to pr_debugs Tero Kristo
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Tero Kristo @ 2011-06-29  9:04 UTC (permalink / raw)
  To: linux-omap

This should be replaced with a proper implementation.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/serial.c |   66 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 067a86b..822c9b8 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -851,17 +851,79 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
  * can call this function when they want to have default behaviour
  * for serial ports (e.g initialize them all as serial ports).
  */
+
+struct serial_mux_conf {
+	char *name;
+	int omap3_mux;
+	int omap4_mux;
+};
+
+#define OMAP3_SERIAL_MUX_IN_PU (OMAP_PIN_INPUT_PULLUP | \
+	OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_OFFOUT_EN | OMAP_MUX_MODE0)
+#define OMAP3_SERIAL_MUX_IN_PD (OMAP_PIN_INPUT_PULLDOWN | \
+	OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_OFFOUT_EN | OMAP_MUX_MODE0)
+#define OMAP3_SERIAL_MUX_IN (OMAP_PIN_INPUT | OMAP_PIN_OFF_INPUT_PULLDOWN | \
+		OMAP_OFFOUT_EN | OMAP_MUX_MODE0)
+#define OMAP3_SERIAL_MUX_OUT (OMAP_PIN_OUTPUT | OMAP_OFF_EN | OMAP_MUX_MODE0)
+#define OMAP4_SERIAL_MUX_IN_PU (OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0)
+#define OMAP4_SERIAL_MUX_OUT (OMAP_PIN_OUTPUT | OMAP_MUX_MODE0)
+#define OMAP4_SERIAL_MUX_IN (OMAP_PIN_INPUT | OMAP_MUX_MODE0)
+
+#define OMAP_SERIAL_NUM_PADS_PER_PORT 4
+
+static const struct serial_mux_conf serial_mux_data[] = {
+	{ "uart1_cts.uart1_cts", OMAP3_SERIAL_MUX_IN, 0, },
+	{ "uart1_rts.uart1_rts", OMAP3_SERIAL_MUX_OUT, 0, },
+	{ "uart1_rx.uart1_rx", OMAP3_SERIAL_MUX_IN, 0, },
+	{ "uart1_tx.uart1_tx", OMAP3_SERIAL_MUX_OUT, 0, },
+	{ "uart2_cts.uart2_cts", OMAP3_SERIAL_MUX_IN_PU,
+		OMAP4_SERIAL_MUX_IN_PU, },
+	{ "uart2_rts.uart2_rts", OMAP3_SERIAL_MUX_OUT, OMAP4_SERIAL_MUX_OUT, },
+	{ "uart2_rx.uart2_rx", OMAP3_SERIAL_MUX_IN, OMAP4_SERIAL_MUX_IN_PU, },
+	{ "uart2_tx.uart2_tx", OMAP3_SERIAL_MUX_OUT, OMAP4_SERIAL_MUX_OUT },
+	{ "uart3_cts_rctx.uart3_cts_rctx", OMAP3_SERIAL_MUX_IN_PD,
+		OMAP4_SERIAL_MUX_IN_PU, },
+	{ "uart3_rts_sd.uart3_rts_sd", OMAP3_SERIAL_MUX_OUT,
+		OMAP4_SERIAL_MUX_OUT, },
+	{ "uart3_rx_irrx.uart3_rx_irrx", OMAP3_SERIAL_MUX_IN,
+		OMAP4_SERIAL_MUX_IN, },
+	{ "uart3_tx_irtx.uart3_tx_irtx", OMAP3_SERIAL_MUX_OUT,
+		OMAP4_SERIAL_MUX_OUT, },
+	{ "uart4_rx.uart4_rx", 0, OMAP4_SERIAL_MUX_IN, },
+	{ "uart4_tx.uart4_tx", 0, OMAP4_SERIAL_MUX_OUT, },
+	{ NULL, 0, 0, },
+	{ NULL, 0, 0, },
+};
+
 void __init omap_serial_init(void)
 {
 	struct omap_uart_state *uart;
 	struct omap_board_data bdata;
+	struct omap_device_pad *pads;
+	int idx;
+	int i;
 
+	pads = kmalloc(sizeof(struct omap_device_pad) * 4, GFP_KERNEL);
 	list_for_each_entry(uart, &uart_list, node) {
 		bdata.id = uart->num;
 		bdata.flags = 0;
-		bdata.pads = NULL;
 		bdata.pads_cnt = 0;
+		bdata.pads = pads;
+
+		for (i = 0; i < OMAP_SERIAL_NUM_PADS_PER_PORT; i++) {
+			idx = bdata.id * OMAP_SERIAL_NUM_PADS_PER_PORT + i;
+			pads[i].name = serial_mux_data[idx].name;
+			pads[i].enable = 0;
+			if (cpu_is_omap34xx())
+				pads[i].enable = serial_mux_data[idx].omap3_mux;
+			if (cpu_is_omap44xx())
+				pads[i].enable = serial_mux_data[idx].omap4_mux;
+			if (pads[i].enable)
+				bdata.pads_cnt++;
+		}
+		if (bdata.pads_cnt == 0)
+			bdata.pads = NULL;
 		omap_serial_init_port(&bdata);
-
 	}
+	kfree(pads);
 }
-- 
1.7.4.1


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCHv4 6/9] OMAP device: change pr_warnings to pr_debugs
  2011-06-29  9:04 [PATCHv4 0/9] PRCM chain interrupt handling Tero Kristo
                   ` (4 preceding siblings ...)
  2011-06-29  9:04 ` [PATCHv4 5/9] TEMP: Serial: Added mux support Tero Kristo
@ 2011-06-29  9:05 ` Tero Kristo
  2011-07-01 22:05   ` Kevin Hilman
  2011-06-29  9:05 ` [PATCHv4 7/9] OMAP: hwmod: enable / disable pad wakeups for a module dynamically Tero Kristo
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Tero Kristo @ 2011-06-29  9:05 UTC (permalink / raw)
  To: linux-omap

Prevents a hang when omap_device would want to print something for
serial console device while enabling / disabling its clocks.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/plat-omap/omap_device.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 49fc0df..c2b8461 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -146,12 +146,12 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
 			odpl->activate_lat_worst = act_lat;
 			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 				odpl->activate_lat = act_lat;
-				pr_warning("omap_device: %s.%d: new worst case "
+				pr_debug("omap_device: %s.%d: new worst case "
 					   "activate latency %d: %llu\n",
 					   od->pdev.name, od->pdev.id,
 					   od->pm_lat_level, act_lat);
 			} else
-				pr_warning("omap_device: %s.%d: activate "
+				pr_debug("omap_device: %s.%d: activate "
 					   "latency %d higher than exptected. "
 					   "(%llu > %d)\n",
 					   od->pdev.name, od->pdev.id,
@@ -214,12 +214,12 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
 			odpl->deactivate_lat_worst = deact_lat;
 			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 				odpl->deactivate_lat = deact_lat;
-				pr_warning("omap_device: %s.%d: new worst case "
+				pr_debug("omap_device: %s.%d: new worst case "
 					   "deactivate latency %d: %llu\n",
 					   od->pdev.name, od->pdev.id,
 					   od->pm_lat_level, deact_lat);
 			} else
-				pr_warning("omap_device: %s.%d: deactivate "
+				pr_debug("omap_device: %s.%d: deactivate "
 					   "latency %d higher than exptected. "
 					   "(%llu > %d)\n",
 					   od->pdev.name, od->pdev.id,
-- 
1.7.4.1


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCHv4 7/9] OMAP: hwmod: enable / disable pad wakeups for a module dynamically
  2011-06-29  9:04 [PATCHv4 0/9] PRCM chain interrupt handling Tero Kristo
                   ` (5 preceding siblings ...)
  2011-06-29  9:05 ` [PATCHv4 6/9] OMAP device: change pr_warnings to pr_debugs Tero Kristo
@ 2011-06-29  9:05 ` Tero Kristo
  2011-07-01 22:18   ` Kevin Hilman
  2011-06-29  9:05 ` [PATCHv4 8/9] TEMP: OMAP: serial: remove padconf hacks Tero Kristo
  2011-06-29  9:05 ` [PATCHv4 9/9] OMAP3: PM: Disable / enable PRCM chain interrupts during wakeup from suspend Tero Kristo
  8 siblings, 1 reply; 22+ messages in thread
From: Tero Kristo @ 2011-06-29  9:05 UTC (permalink / raw)
  To: linux-omap

PRCM chain interrupt registration is done now as part of
omap_hwmod_enable_wakeup() and omap_hwmod_disable_wakeup() calls. This
allows module ISR:s to be called when the module is idle but an IO_PAD
event is detected on the module input pads.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 293fa6c..f12fe89 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2123,6 +2123,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_enable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	omap_prcm_register_pad_irqs(oh->mux, oh->mpu_irqs[0].irq);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
@@ -2153,6 +2154,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_disable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	omap_prcm_unregister_pad_irqs(oh->mux);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
-- 
1.7.4.1


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCHv4 8/9] TEMP: OMAP: serial: remove padconf hacks
  2011-06-29  9:04 [PATCHv4 0/9] PRCM chain interrupt handling Tero Kristo
                   ` (6 preceding siblings ...)
  2011-06-29  9:05 ` [PATCHv4 7/9] OMAP: hwmod: enable / disable pad wakeups for a module dynamically Tero Kristo
@ 2011-06-29  9:05 ` Tero Kristo
  2011-06-29  9:05 ` [PATCHv4 9/9] OMAP3: PM: Disable / enable PRCM chain interrupts during wakeup from suspend Tero Kristo
  8 siblings, 0 replies; 22+ messages in thread
From: Tero Kristo @ 2011-06-29  9:05 UTC (permalink / raw)
  To: linux-omap

These are no longer needed as omap_hwmod takes care of multiplexing of pads.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/serial.c |   25 +------------------------
 1 files changed, 1 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 822c9b8..f8fafdd 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -73,7 +73,6 @@ struct omap_uart_state {
 	void __iomem *wk_st;
 	void __iomem *wk_en;
 	u32 wk_mask;
-	u32 padconf;
 	u32 dma_enabled;
 
 	struct clk *ick;
@@ -309,13 +308,6 @@ static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
 		v |= uart->wk_mask;
 		__raw_writel(v, uart->wk_en);
 	}
-
-	/* Ensure IOPAD wake-enables are set */
-	if (cpu_is_omap34xx() && uart->padconf) {
-		u16 v = omap_ctrl_readw(uart->padconf);
-		v |= OMAP3_PADCONF_WAKEUPENABLE0;
-		omap_ctrl_writew(v, uart->padconf);
-	}
 }
 
 static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
@@ -326,13 +318,6 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
 		v &= ~uart->wk_mask;
 		__raw_writel(v, uart->wk_en);
 	}
-
-	/* Ensure IOPAD wake-enables are cleared */
-	if (cpu_is_omap34xx() && uart->padconf) {
-		u16 v = omap_ctrl_readw(uart->padconf);
-		v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
-		omap_ctrl_writew(v, uart->padconf);
-	}
 }
 
 static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
@@ -479,7 +464,6 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
 		u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
 		u32 wk_mask = 0;
-		u32 padconf = 0;
 
 		/* XXX These PRM accesses do not belong here */
 		uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
@@ -487,23 +471,18 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 		switch (uart->num) {
 		case 0:
 			wk_mask = OMAP3430_ST_UART1_MASK;
-			padconf = 0x182;
 			break;
 		case 1:
 			wk_mask = OMAP3430_ST_UART2_MASK;
-			padconf = 0x17a;
 			break;
 		case 2:
 			wk_mask = OMAP3430_ST_UART3_MASK;
-			padconf = 0x19e;
 			break;
 		case 3:
 			wk_mask = OMAP3630_ST_UART4_MASK;
-			padconf = 0x0d2;
 			break;
 		}
 		uart->wk_mask = wk_mask;
-		uart->padconf = padconf;
 	} else if (cpu_is_omap24xx()) {
 		u32 wk_mask = 0;
 		u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
@@ -533,7 +512,6 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 		uart->wk_en = NULL;
 		uart->wk_st = NULL;
 		uart->wk_mask = 0;
-		uart->padconf = 0;
 	}
 
 	uart->irqflags |= IRQF_SHARED;
@@ -833,8 +811,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 
 	console_unlock();
 
-	if ((cpu_is_omap34xx() && uart->padconf) ||
-	    (uart->wk_en && uart->wk_mask)) {
+	if (uart->oh->mux || (uart->wk_en && uart->wk_mask)) {
 		device_init_wakeup(&od->pdev.dev, true);
 		DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
 	}
-- 
1.7.4.1


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCHv4 9/9] OMAP3: PM: Disable / enable PRCM chain interrupts during wakeup from suspend
  2011-06-29  9:04 [PATCHv4 0/9] PRCM chain interrupt handling Tero Kristo
                   ` (7 preceding siblings ...)
  2011-06-29  9:05 ` [PATCHv4 8/9] TEMP: OMAP: serial: remove padconf hacks Tero Kristo
@ 2011-06-29  9:05 ` Tero Kristo
  2011-07-01 20:10   ` Kevin Hilman
  8 siblings, 1 reply; 22+ messages in thread
From: Tero Kristo @ 2011-06-29  9:05 UTC (permalink / raw)
  To: linux-omap

This prevents system hang while attempting to access suspended console.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/pm34xx.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index e626a3d..dae0a8a 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -418,6 +418,10 @@ void omap_sram_idle(void)
 	pwrdm_post_transition();
 
 	clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
+	if (suspend_state != PM_SUSPEND_ON) {
+		disable_irq(prcm_io_irq);
+		disable_irq(prcm_wkup_irq);
+	}
 }
 
 int omap3_can_sleep(void)
@@ -524,6 +528,8 @@ static void omap3_pm_end(void)
 	suspend_state = PM_SUSPEND_ON;
 	omap_uart_enable_irqs(1);
 	enable_hlt();
+	enable_irq(prcm_io_irq);
+	enable_irq(prcm_wkup_irq);
 	return;
 }
 
-- 
1.7.4.1


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism
  2011-06-29  9:04 ` [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism Tero Kristo
@ 2011-06-29 16:53   ` Felipe Balbi
  2011-06-29 16:54     ` Felipe Balbi
  2011-06-30  5:51     ` Tero Kristo
  2011-07-01 21:58   ` Kevin Hilman
  1 sibling, 2 replies; 22+ messages in thread
From: Felipe Balbi @ 2011-06-29 16:53 UTC (permalink / raw)
  To: Tero Kristo
  Cc: linux-omap, Thomas Petazzoni, Avinash.H.M, Kevin Hilman, Cousson,
	Benoit, Tony Lindgren, Govindraj.R

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

Hi,

On Wed, Jun 29, 2011 at 12:04:55PM +0300, Tero Kristo wrote:
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 96a7624..89cf027 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -880,20 +824,35 @@ static int __init omap3_pm_init(void)
>  	/* XXX prcm_setup_regs needs to be before enabling hw
>  	 * supervised mode for powerdomains */
>  	prcm_setup_regs();
> +	ret = omap_prcm_irq_init();
> +	if (ret) {
> +		pr_err("omap_prcm_irq_init() failed with %d\n", ret);
> +		goto err_prcm_irq_init;
> +	}
> +
> +	prcm_wkup_irq = omap_prcm_event_to_irq("wkup");
> +	prcm_io_irq = omap_prcm_event_to_irq("io");
> +
> +	ret = request_irq(prcm_wkup_irq, _prcm_int_handle_wakeup,
> +			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_wkup", NULL);

does this _have_ to be all in hardirq context ?

> -	ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
> -			  (irq_handler_t)prcm_interrupt_handler,
> -			  IRQF_DISABLED, "prcm", NULL);
>  	if (ret) {
> -		printk(KERN_ERR "request_irq failed to register for 0x%x\n",
> -		       INT_34XX_PRCM_MPU_IRQ);
> -		goto err1;
> +		printk(KERN_ERR "Failed to request prcm_wkup irq\n");
> +		goto err_prcm_wkup;
> +	}
> +
> +	ret = request_irq(prcm_io_irq, _prcm_int_handle_wakeup,
> +			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_io", NULL);

same here...

> diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
> index 6be1438..794e451 100644
> --- a/arch/arm/mach-omap2/prcm.c
> +++ b/arch/arm/mach-omap2/prcm.c
> @@ -23,6 +23,8 @@
>  #include <linux/clk.h>
>  #include <linux/io.h>
>  #include <linux/delay.h>
> +#include <linux/irq.h>
> +#include <linux/slab.h>
>  
>  #include <mach/system.h>
>  #include <plat/common.h>
> @@ -45,6 +47,167 @@ void __iomem *cm2_base;
>  
>  #define MAX_MODULE_ENABLE_WAIT		100000
>  
> +/* Setup for the interrupt handling based on used platform */
> +static struct omap_prcm_irq_setup *irq_setup;

you can set this is irq_chip data, then you can:

> +static void prcm_irq_ack(struct irq_data *data)
> +{
	struct omap_prcm_irq_setup	*irq_setup = irq_data_get_irq_chip_data(data)
	unsigned int			prcm_irq = data->irq - irq_setup->base;

	irq_setup->ack_event(prcm_irq);
> +}

ditto to all other operations.

> +static struct irq_chip_generic *prcm_irq_chips[OMAP_PRCM_MAX_NR_PENDING_REG];

can't you allocate this dynamically ???

> +/*
> + * PRCM Interrupt Handler
> + *
> + * The PRM_IRQSTATUS_MPU register indicates if there are any pending
> + * interrupts from the PRCM for the MPU. These bits must be cleared in
> + * order to clear the PRCM interrupt. The PRCM interrupt handler is
> + * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear
> + * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU
> + * register indicates that a wake-up event is pending for the MPU and
> + * this bit can only be cleared if the all the wake-up events latched
> + * in the various PM_WKST_x registers have been cleared. The interrupt
> + * handler is implemented using a do-while loop so that if a wake-up
> + * event occurred during the processing of the prcm interrupt handler
> + * (setting a bit in the corresponding PM_WKST_x register and thus
> + * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register)
> + * this would be handled.
> + */
> +static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
> +{
> +	unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG];
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +
> +	/*
> +	 * Loop until all pending irqs are handled, since
> +	 * generic_handle_irq(), called by prcm_irq_handle_virtirqs()
> +	 * can cause new irqs to come
> +	 */
> +	while (1) {
> +		unsigned int virtirq;
> +
> +		chip->irq_ack(&desc->irq_data);
> +
> +		memset(pending, 0, sizeof(pending));
> +		irq_setup->pending_events(pending);
> +
> +		/* No bit set, then all IRQs are handled */
> +		if (find_first_bit(pending, OMAP_PRCM_NR_IRQS)
> +		    >= OMAP_PRCM_NR_IRQS) {
> +			chip->irq_unmask(&desc->irq_data);
> +			break;
> +		}
> +
> +		/*
> +		 * Loop on all currently pending irqs so that new irqs
> +		 * cannot starve previously pending irqs
> +		 */
> +		for_each_set_bit(virtirq, pending, OMAP_PRCM_NR_IRQS)
> +			generic_handle_irq(OMAP_PRCM_IRQ_BASE + virtirq);

if you use nested IRQ threads, you could be using
handle_nested_irq(irq);

> +		chip->irq_unmask(&desc->irq_data);
> +	}
> +}
> +
> +/*
> + * Given a PRCM event name, returns the corresponding IRQ on which the
> + * handler should be registered.
> + */
> +int omap_prcm_event_to_irq(const char *name)
> +{
> +	int i;
> +
> +	for (i = 0; i < irq_setup->num_irqs; i++)
> +		if (!strcmp(irq_setup->irqs[i].name, name))
> +			return OMAP_PRCM_IRQ_BASE + irq_setup->irqs[i].offset;
> +
> +	return -ENOENT;
> +}
> +
> +/*
> + * Prepare the array of PRCM events corresponding to the current SoC,
> + * and set-up the chained interrupt handler mechanism.
> + */
> +int __init omap_prcm_irq_init(void)
> +{
> +	int i;
> +	struct irq_chip_generic *gc;
> +	struct irq_chip_type *ct;
> +	u32 mask[2] = { 0, 0 };
> +	int offset;
> +	int max_irq = 0;
> +
> +	for (i = 0; i < irq_setup->num_irqs; i++)

how about using irq_alloc_descs() ?? Then we can make use of Sparse IRQ
numbers and avoid passing irq_base/irq_end and adding that weird ifdef
hackery to get NR_IRQS right.

> diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
> index 5a25098..23b9680 100644
> --- a/arch/arm/plat-omap/include/plat/irqs.h
> +++ b/arch/arm/plat-omap/include/plat/irqs.h
> @@ -366,7 +366,14 @@
>  #define OMAP_MAX_GPIO_LINES	192
>  #define IH_GPIO_BASE		(128 + IH2_BASE)
>  #define IH_MPUIO_BASE		(OMAP_MAX_GPIO_LINES + IH_GPIO_BASE)
> -#define OMAP_IRQ_END		(IH_MPUIO_BASE + 16)
> +#define OMAP_MPUIO_IRQ_END	(IH_MPUIO_BASE + 16)
> +
> +/* 64 IRQs for the PRCM (32 are needed on OMAP3, 64 on OMAP4) */
> +#define OMAP_PRCM_IRQ_BASE      (OMAP_MPUIO_IRQ_END)
> +#define OMAP_PRCM_NR_IRQS       64
> +#define OMAP_PRCM_IRQ_END       (OMAP_PRCM_IRQ_BASE + OMAP_PRCM_NR_IRQS)
> +
> +#define OMAP_IRQ_END            (OMAP_PRCM_IRQ_END)

this is unnecessary with Sparse IRQ numbers and IMHO we should aim for
that. See the very simple conversion that I sent for the very old retu
driver [1] and [2] and you'll see that with time, we could get rid of
NR_IRQS altogether.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism
  2011-06-29 16:53   ` Felipe Balbi
@ 2011-06-29 16:54     ` Felipe Balbi
  2011-06-30  5:51     ` Tero Kristo
  1 sibling, 0 replies; 22+ messages in thread
From: Felipe Balbi @ 2011-06-29 16:54 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: Tero Kristo, linux-omap, Thomas Petazzoni, Avinash.H.M,
	Kevin Hilman, Cousson, Benoit, Tony Lindgren, Govindraj.R

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

On Wed, Jun 29, 2011 at 07:53:19PM +0300, Felipe Balbi wrote:
> On Wed, Jun 29, 2011 at 12:04:55PM +0300, Tero Kristo wrote:
> > diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> > index 96a7624..89cf027 100644
> > --- a/arch/arm/mach-omap2/pm34xx.c
> > +++ b/arch/arm/mach-omap2/pm34xx.c
> > @@ -880,20 +824,35 @@ static int __init omap3_pm_init(void)
> >  	/* XXX prcm_setup_regs needs to be before enabling hw
> >  	 * supervised mode for powerdomains */
> >  	prcm_setup_regs();
> > +	ret = omap_prcm_irq_init();
> > +	if (ret) {
> > +		pr_err("omap_prcm_irq_init() failed with %d\n", ret);
> > +		goto err_prcm_irq_init;
> > +	}
> > +
> > +	prcm_wkup_irq = omap_prcm_event_to_irq("wkup");
> > +	prcm_io_irq = omap_prcm_event_to_irq("io");
> > +
> > +	ret = request_irq(prcm_wkup_irq, _prcm_int_handle_wakeup,
> > +			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_wkup", NULL);
> 
> does this _have_ to be all in hardirq context ?
> 
> > -	ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
> > -			  (irq_handler_t)prcm_interrupt_handler,
> > -			  IRQF_DISABLED, "prcm", NULL);
> >  	if (ret) {
> > -		printk(KERN_ERR "request_irq failed to register for 0x%x\n",
> > -		       INT_34XX_PRCM_MPU_IRQ);
> > -		goto err1;
> > +		printk(KERN_ERR "Failed to request prcm_wkup irq\n");
> > +		goto err_prcm_wkup;
> > +	}
> > +
> > +	ret = request_irq(prcm_io_irq, _prcm_int_handle_wakeup,
> > +			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_io", NULL);
> 
> same here...
> 
> > diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
> > index 6be1438..794e451 100644
> > --- a/arch/arm/mach-omap2/prcm.c
> > +++ b/arch/arm/mach-omap2/prcm.c
> > @@ -23,6 +23,8 @@
> >  #include <linux/clk.h>
> >  #include <linux/io.h>
> >  #include <linux/delay.h>
> > +#include <linux/irq.h>
> > +#include <linux/slab.h>
> >  
> >  #include <mach/system.h>
> >  #include <plat/common.h>
> > @@ -45,6 +47,167 @@ void __iomem *cm2_base;
> >  
> >  #define MAX_MODULE_ENABLE_WAIT		100000
> >  
> > +/* Setup for the interrupt handling based on used platform */
> > +static struct omap_prcm_irq_setup *irq_setup;
> 
> you can set this is irq_chip data, then you can:
> 
> > +static void prcm_irq_ack(struct irq_data *data)
> > +{
> 	struct omap_prcm_irq_setup	*irq_setup = irq_data_get_irq_chip_data(data)
> 	unsigned int			prcm_irq = data->irq - irq_setup->base;
> 
> 	irq_setup->ack_event(prcm_irq);
> > +}
> 
> ditto to all other operations.
> 
> > +static struct irq_chip_generic *prcm_irq_chips[OMAP_PRCM_MAX_NR_PENDING_REG];
> 
> can't you allocate this dynamically ???
> 
> > +/*
> > + * PRCM Interrupt Handler
> > + *
> > + * The PRM_IRQSTATUS_MPU register indicates if there are any pending
> > + * interrupts from the PRCM for the MPU. These bits must be cleared in
> > + * order to clear the PRCM interrupt. The PRCM interrupt handler is
> > + * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear
> > + * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU
> > + * register indicates that a wake-up event is pending for the MPU and
> > + * this bit can only be cleared if the all the wake-up events latched
> > + * in the various PM_WKST_x registers have been cleared. The interrupt
> > + * handler is implemented using a do-while loop so that if a wake-up
> > + * event occurred during the processing of the prcm interrupt handler
> > + * (setting a bit in the corresponding PM_WKST_x register and thus
> > + * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register)
> > + * this would be handled.
> > + */
> > +static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
> > +{
> > +	unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG];
> > +	struct irq_chip *chip = irq_desc_get_chip(desc);
> > +
> > +	/*
> > +	 * Loop until all pending irqs are handled, since
> > +	 * generic_handle_irq(), called by prcm_irq_handle_virtirqs()
> > +	 * can cause new irqs to come
> > +	 */
> > +	while (1) {
> > +		unsigned int virtirq;
> > +
> > +		chip->irq_ack(&desc->irq_data);
> > +
> > +		memset(pending, 0, sizeof(pending));
> > +		irq_setup->pending_events(pending);
> > +
> > +		/* No bit set, then all IRQs are handled */
> > +		if (find_first_bit(pending, OMAP_PRCM_NR_IRQS)
> > +		    >= OMAP_PRCM_NR_IRQS) {
> > +			chip->irq_unmask(&desc->irq_data);
> > +			break;
> > +		}
> > +
> > +		/*
> > +		 * Loop on all currently pending irqs so that new irqs
> > +		 * cannot starve previously pending irqs
> > +		 */
> > +		for_each_set_bit(virtirq, pending, OMAP_PRCM_NR_IRQS)
> > +			generic_handle_irq(OMAP_PRCM_IRQ_BASE + virtirq);
> 
> if you use nested IRQ threads, you could be using
> handle_nested_irq(irq);
> 
> > +		chip->irq_unmask(&desc->irq_data);
> > +	}
> > +}
> > +
> > +/*
> > + * Given a PRCM event name, returns the corresponding IRQ on which the
> > + * handler should be registered.
> > + */
> > +int omap_prcm_event_to_irq(const char *name)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < irq_setup->num_irqs; i++)
> > +		if (!strcmp(irq_setup->irqs[i].name, name))
> > +			return OMAP_PRCM_IRQ_BASE + irq_setup->irqs[i].offset;
> > +
> > +	return -ENOENT;
> > +}
> > +
> > +/*
> > + * Prepare the array of PRCM events corresponding to the current SoC,
> > + * and set-up the chained interrupt handler mechanism.
> > + */
> > +int __init omap_prcm_irq_init(void)
> > +{
> > +	int i;
> > +	struct irq_chip_generic *gc;
> > +	struct irq_chip_type *ct;
> > +	u32 mask[2] = { 0, 0 };
> > +	int offset;
> > +	int max_irq = 0;
> > +
> > +	for (i = 0; i < irq_setup->num_irqs; i++)
> 
> how about using irq_alloc_descs() ?? Then we can make use of Sparse IRQ
> numbers and avoid passing irq_base/irq_end and adding that weird ifdef
> hackery to get NR_IRQS right.
> 
> > diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
> > index 5a25098..23b9680 100644
> > --- a/arch/arm/plat-omap/include/plat/irqs.h
> > +++ b/arch/arm/plat-omap/include/plat/irqs.h
> > @@ -366,7 +366,14 @@
> >  #define OMAP_MAX_GPIO_LINES	192
> >  #define IH_GPIO_BASE		(128 + IH2_BASE)
> >  #define IH_MPUIO_BASE		(OMAP_MAX_GPIO_LINES + IH_GPIO_BASE)
> > -#define OMAP_IRQ_END		(IH_MPUIO_BASE + 16)
> > +#define OMAP_MPUIO_IRQ_END	(IH_MPUIO_BASE + 16)
> > +
> > +/* 64 IRQs for the PRCM (32 are needed on OMAP3, 64 on OMAP4) */
> > +#define OMAP_PRCM_IRQ_BASE      (OMAP_MPUIO_IRQ_END)
> > +#define OMAP_PRCM_NR_IRQS       64
> > +#define OMAP_PRCM_IRQ_END       (OMAP_PRCM_IRQ_BASE + OMAP_PRCM_NR_IRQS)
> > +
> > +#define OMAP_IRQ_END            (OMAP_PRCM_IRQ_END)
> 
> this is unnecessary with Sparse IRQ numbers and IMHO we should aim for
> that. See the very simple conversion that I sent for the very old retu
> driver [1] and [2] and you'll see that with time, we could get rid of
> NR_IRQS altogether.

[1] http://marc.info/?l=linux-omap&m=130934802215308&w=2
[2] http://marc.info/?l=linux-omap&m=130934804515353&w=2

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism
  2011-06-29 16:53   ` Felipe Balbi
  2011-06-29 16:54     ` Felipe Balbi
@ 2011-06-30  5:51     ` Tero Kristo
  2011-06-30  9:11       ` Felipe Balbi
  1 sibling, 1 reply; 22+ messages in thread
From: Tero Kristo @ 2011-06-30  5:51 UTC (permalink / raw)
  To: Balbi, Felipe
  Cc: linux-omap, Thomas Petazzoni, Mahadeva, Avinash, Hilman, Kevin,
	Cousson, Benoit, Tony Lindgren, R, Govindraj

On Wed, 2011-06-29 at 18:53 +0200, Balbi, Felipe wrote:
> Hi,
> 
> On Wed, Jun 29, 2011 at 12:04:55PM +0300, Tero Kristo wrote:
> > diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> > index 96a7624..89cf027 100644
> > --- a/arch/arm/mach-omap2/pm34xx.c
> > +++ b/arch/arm/mach-omap2/pm34xx.c
> > @@ -880,20 +824,35 @@ static int __init omap3_pm_init(void)
> >  	/* XXX prcm_setup_regs needs to be before enabling hw
> >  	 * supervised mode for powerdomains */
> >  	prcm_setup_regs();
> > +	ret = omap_prcm_irq_init();
> > +	if (ret) {
> > +		pr_err("omap_prcm_irq_init() failed with %d\n", ret);
> > +		goto err_prcm_irq_init;
> > +	}
> > +
> > +	prcm_wkup_irq = omap_prcm_event_to_irq("wkup");
> > +	prcm_io_irq = omap_prcm_event_to_irq("io");
> > +
> > +	ret = request_irq(prcm_wkup_irq, _prcm_int_handle_wakeup,
> > +			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_wkup", NULL);
> 
> does this _have_ to be all in hardirq context ?

Not really, imo this does not need to be done in an interrupt at all.
The wakeup event ack can be done just before entering next idle, as I
did in a previous version of this set, but it did not receive that
positive comments yet. I will probably try to push this idea forward
once this set is pulled.

> 
> > -	ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
> > -			  (irq_handler_t)prcm_interrupt_handler,
> > -			  IRQF_DISABLED, "prcm", NULL);
> >  	if (ret) {
> > -		printk(KERN_ERR "request_irq failed to register for 0x%x\n",
> > -		       INT_34XX_PRCM_MPU_IRQ);
> > -		goto err1;
> > +		printk(KERN_ERR "Failed to request prcm_wkup irq\n");
> > +		goto err_prcm_wkup;
> > +	}
> > +
> > +	ret = request_irq(prcm_io_irq, _prcm_int_handle_wakeup,
> > +			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_io", NULL);
> 
> same here...

Same... though the interrupt does not really do that much even if the
code looks horrible with the looping around. Usually only one wakeup
source is active.

> 
> > diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
> > index 6be1438..794e451 100644
> > --- a/arch/arm/mach-omap2/prcm.c
> > +++ b/arch/arm/mach-omap2/prcm.c
> > @@ -23,6 +23,8 @@
> >  #include <linux/clk.h>
> >  #include <linux/io.h>
> >  #include <linux/delay.h>
> > +#include <linux/irq.h>
> > +#include <linux/slab.h>
> >  
> >  #include <mach/system.h>
> >  #include <plat/common.h>
> > @@ -45,6 +47,167 @@ void __iomem *cm2_base;
> >  
> >  #define MAX_MODULE_ENABLE_WAIT		100000
> >  
> > +/* Setup for the interrupt handling based on used platform */
> > +static struct omap_prcm_irq_setup *irq_setup;
> 
> you can set this is irq_chip data, then you can:
> 
> > +static void prcm_irq_ack(struct irq_data *data)
> > +{
> 	struct omap_prcm_irq_setup	*irq_setup = irq_data_get_irq_chip_data(data)
> 	unsigned int			prcm_irq = data->irq - irq_setup->base;
> 
> 	irq_setup->ack_event(prcm_irq);
> > +}
> 
> ditto to all other operations.

This is related to the dynamic allocation of irq numbers you speak of
later I think... anyway, I'll take a look at this.

> > +static struct irq_chip_generic *prcm_irq_chips[OMAP_PRCM_MAX_NR_PENDING_REG];
> 
> can't you allocate this dynamically ???

Well yea, but it is only 1 or 2 pointers. The code for dynamic
allocation will eat more than 4 bytes easily.

> 
> > +/*
> > + * PRCM Interrupt Handler
> > + *
> > + * The PRM_IRQSTATUS_MPU register indicates if there are any pending
> > + * interrupts from the PRCM for the MPU. These bits must be cleared in
> > + * order to clear the PRCM interrupt. The PRCM interrupt handler is
> > + * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear
> > + * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU
> > + * register indicates that a wake-up event is pending for the MPU and
> > + * this bit can only be cleared if the all the wake-up events latched
> > + * in the various PM_WKST_x registers have been cleared. The interrupt
> > + * handler is implemented using a do-while loop so that if a wake-up
> > + * event occurred during the processing of the prcm interrupt handler
> > + * (setting a bit in the corresponding PM_WKST_x register and thus
> > + * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register)
> > + * this would be handled.
> > + */
> > +static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
> > +{
> > +	unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG];
> > +	struct irq_chip *chip = irq_desc_get_chip(desc);
> > +
> > +	/*
> > +	 * Loop until all pending irqs are handled, since
> > +	 * generic_handle_irq(), called by prcm_irq_handle_virtirqs()
> > +	 * can cause new irqs to come
> > +	 */
> > +	while (1) {
> > +		unsigned int virtirq;
> > +
> > +		chip->irq_ack(&desc->irq_data);
> > +
> > +		memset(pending, 0, sizeof(pending));
> > +		irq_setup->pending_events(pending);
> > +
> > +		/* No bit set, then all IRQs are handled */
> > +		if (find_first_bit(pending, OMAP_PRCM_NR_IRQS)
> > +		    >= OMAP_PRCM_NR_IRQS) {
> > +			chip->irq_unmask(&desc->irq_data);
> > +			break;
> > +		}
> > +
> > +		/*
> > +		 * Loop on all currently pending irqs so that new irqs
> > +		 * cannot starve previously pending irqs
> > +		 */
> > +		for_each_set_bit(virtirq, pending, OMAP_PRCM_NR_IRQS)
> > +			generic_handle_irq(OMAP_PRCM_IRQ_BASE + virtirq);
> 
> if you use nested IRQ threads, you could be using
> handle_nested_irq(irq);

1st level PRCM interrupt can't be a thread I think. I don't think
chained interrupt handlers even support that, and even if they did,
there might be reasons where in some cases we want to execute some of
the PRCM events as hard irqs.

> 
> > +		chip->irq_unmask(&desc->irq_data);
> > +	}
> > +}
> > +
> > +/*
> > + * Given a PRCM event name, returns the corresponding IRQ on which the
> > + * handler should be registered.
> > + */
> > +int omap_prcm_event_to_irq(const char *name)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < irq_setup->num_irqs; i++)
> > +		if (!strcmp(irq_setup->irqs[i].name, name))
> > +			return OMAP_PRCM_IRQ_BASE + irq_setup->irqs[i].offset;
> > +
> > +	return -ENOENT;
> > +}
> > +
> > +/*
> > + * Prepare the array of PRCM events corresponding to the current SoC,
> > + * and set-up the chained interrupt handler mechanism.
> > + */
> > +int __init omap_prcm_irq_init(void)
> > +{
> > +	int i;
> > +	struct irq_chip_generic *gc;
> > +	struct irq_chip_type *ct;
> > +	u32 mask[2] = { 0, 0 };
> > +	int offset;
> > +	int max_irq = 0;
> > +
> > +	for (i = 0; i < irq_setup->num_irqs; i++)
> 
> how about using irq_alloc_descs() ?? Then we can make use of Sparse IRQ
> numbers and avoid passing irq_base/irq_end and adding that weird ifdef
> hackery to get NR_IRQS right.

I'll take a look at this and the references you provided later on today.

> 
> > diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
> > index 5a25098..23b9680 100644
> > --- a/arch/arm/plat-omap/include/plat/irqs.h
> > +++ b/arch/arm/plat-omap/include/plat/irqs.h
> > @@ -366,7 +366,14 @@
> >  #define OMAP_MAX_GPIO_LINES	192
> >  #define IH_GPIO_BASE		(128 + IH2_BASE)
> >  #define IH_MPUIO_BASE		(OMAP_MAX_GPIO_LINES + IH_GPIO_BASE)
> > -#define OMAP_IRQ_END		(IH_MPUIO_BASE + 16)
> > +#define OMAP_MPUIO_IRQ_END	(IH_MPUIO_BASE + 16)
> > +
> > +/* 64 IRQs for the PRCM (32 are needed on OMAP3, 64 on OMAP4) */
> > +#define OMAP_PRCM_IRQ_BASE      (OMAP_MPUIO_IRQ_END)
> > +#define OMAP_PRCM_NR_IRQS       64
> > +#define OMAP_PRCM_IRQ_END       (OMAP_PRCM_IRQ_BASE + OMAP_PRCM_NR_IRQS)
> > +
> > +#define OMAP_IRQ_END            (OMAP_PRCM_IRQ_END)
> 
> this is unnecessary with Sparse IRQ numbers and IMHO we should aim for
> that. See the very simple conversion that I sent for the very old retu
> driver [1] and [2] and you'll see that with time, we could get rid of
> NR_IRQS altogether.
> 



Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism
  2011-06-30  5:51     ` Tero Kristo
@ 2011-06-30  9:11       ` Felipe Balbi
  0 siblings, 0 replies; 22+ messages in thread
From: Felipe Balbi @ 2011-06-30  9:11 UTC (permalink / raw)
  To: Tero Kristo
  Cc: Balbi, Felipe, linux-omap, Thomas Petazzoni, Mahadeva, Avinash,
	Hilman, Kevin, Cousson, Benoit, Tony Lindgren, R, Govindraj

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

Hi,

On Thu, Jun 30, 2011 at 08:51:39AM +0300, Tero Kristo wrote:
> On Wed, 2011-06-29 at 18:53 +0200, Balbi, Felipe wrote:
> > Hi,
> > 
> > On Wed, Jun 29, 2011 at 12:04:55PM +0300, Tero Kristo wrote:
> > > diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> > > index 96a7624..89cf027 100644
> > > --- a/arch/arm/mach-omap2/pm34xx.c
> > > +++ b/arch/arm/mach-omap2/pm34xx.c
> > > @@ -880,20 +824,35 @@ static int __init omap3_pm_init(void)
> > >  	/* XXX prcm_setup_regs needs to be before enabling hw
> > >  	 * supervised mode for powerdomains */
> > >  	prcm_setup_regs();
> > > +	ret = omap_prcm_irq_init();
> > > +	if (ret) {
> > > +		pr_err("omap_prcm_irq_init() failed with %d\n", ret);
> > > +		goto err_prcm_irq_init;
> > > +	}
> > > +
> > > +	prcm_wkup_irq = omap_prcm_event_to_irq("wkup");
> > > +	prcm_io_irq = omap_prcm_event_to_irq("io");
> > > +
> > > +	ret = request_irq(prcm_wkup_irq, _prcm_int_handle_wakeup,
> > > +			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_wkup", NULL);
> > 
> > does this _have_ to be all in hardirq context ?
> 
> Not really, imo this does not need to be done in an interrupt at all.
> The wakeup event ack can be done just before entering next idle, as I
> did in a previous version of this set, but it did not receive that
> positive comments yet. I will probably try to push this idea forward
> once this set is pulled.

I see... BTW, IRQF_DISABLED is a nop now, you don't need it. I missed
that before ;-)

> > > diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
> > > index 6be1438..794e451 100644
> > > --- a/arch/arm/mach-omap2/prcm.c
> > > +++ b/arch/arm/mach-omap2/prcm.c
> > > @@ -23,6 +23,8 @@
> > >  #include <linux/clk.h>
> > >  #include <linux/io.h>
> > >  #include <linux/delay.h>
> > > +#include <linux/irq.h>
> > > +#include <linux/slab.h>
> > >  
> > >  #include <mach/system.h>
> > >  #include <plat/common.h>
> > > @@ -45,6 +47,167 @@ void __iomem *cm2_base;
> > >  
> > >  #define MAX_MODULE_ENABLE_WAIT		100000
> > >  
> > > +/* Setup for the interrupt handling based on used platform */
> > > +static struct omap_prcm_irq_setup *irq_setup;
> > 
> > you can set this is irq_chip data, then you can:
> > 
> > > +static void prcm_irq_ack(struct irq_data *data)
> > > +{
> > 	struct omap_prcm_irq_setup	*irq_setup = irq_data_get_irq_chip_data(data)
> > 	unsigned int			prcm_irq = data->irq - irq_setup->base;
> > 
> > 	irq_setup->ack_event(prcm_irq);
> > > +}
> > 
> > ditto to all other operations.
> 
> This is related to the dynamic allocation of irq numbers you speak of
> later I think... anyway, I'll take a look at this.

not really, you already set something as data to that function. But I
guess it's the generic irq chip ? Even in that case, you should be able
to access struct omap_prcm_irq_set from struct irq_data.

> > > +static struct irq_chip_generic *prcm_irq_chips[OMAP_PRCM_MAX_NR_PENDING_REG];
> > 
> > can't you allocate this dynamically ???
> 
> Well yea, but it is only 1 or 2 pointers. The code for dynamic
> allocation will eat more than 4 bytes easily.

fair enough...

> > > +/*
> > > + * PRCM Interrupt Handler
> > > + *
> > > + * The PRM_IRQSTATUS_MPU register indicates if there are any pending
> > > + * interrupts from the PRCM for the MPU. These bits must be cleared in
> > > + * order to clear the PRCM interrupt. The PRCM interrupt handler is
> > > + * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear
> > > + * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU
> > > + * register indicates that a wake-up event is pending for the MPU and
> > > + * this bit can only be cleared if the all the wake-up events latched
> > > + * in the various PM_WKST_x registers have been cleared. The interrupt
> > > + * handler is implemented using a do-while loop so that if a wake-up
> > > + * event occurred during the processing of the prcm interrupt handler
> > > + * (setting a bit in the corresponding PM_WKST_x register and thus
> > > + * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register)
> > > + * this would be handled.
> > > + */
> > > +static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
> > > +{
> > > +	unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG];
> > > +	struct irq_chip *chip = irq_desc_get_chip(desc);
> > > +
> > > +	/*
> > > +	 * Loop until all pending irqs are handled, since
> > > +	 * generic_handle_irq(), called by prcm_irq_handle_virtirqs()
> > > +	 * can cause new irqs to come
> > > +	 */
> > > +	while (1) {
> > > +		unsigned int virtirq;
> > > +
> > > +		chip->irq_ack(&desc->irq_data);
> > > +
> > > +		memset(pending, 0, sizeof(pending));
> > > +		irq_setup->pending_events(pending);
> > > +
> > > +		/* No bit set, then all IRQs are handled */
> > > +		if (find_first_bit(pending, OMAP_PRCM_NR_IRQS)
> > > +		    >= OMAP_PRCM_NR_IRQS) {
> > > +			chip->irq_unmask(&desc->irq_data);
> > > +			break;
> > > +		}
> > > +
> > > +		/*
> > > +		 * Loop on all currently pending irqs so that new irqs
> > > +		 * cannot starve previously pending irqs
> > > +		 */
> > > +		for_each_set_bit(virtirq, pending, OMAP_PRCM_NR_IRQS)
> > > +			generic_handle_irq(OMAP_PRCM_IRQ_BASE + virtirq);
> > 
> > if you use nested IRQ threads, you could be using
> > handle_nested_irq(irq);
> 
> 1st level PRCM interrupt can't be a thread I think. I don't think

technically they can, now if it's fair to do that, I doubt. But I tend
to agree with tglx when he says top half should only check if the IRQ
comes from this device, then we spend very little time on hardirq
context and since IRQ threads are the next big thing after hardirqs,
there shouldn't be too much delay... hopefully

> chained interrupt handlers even support that, and even if they did,

no, chained can't fire another threads, but if they are already a
thread, the chained handler should run on the same thread, at least
that's how I understood the implementation.

> there might be reasons where in some cases we want to execute some of
> the PRCM events as hard irqs.

I don't see the point, after you know which interrupts you must handle,
there shouldn't be many things preventing you from doing the handling
itself in a thread. The IRQ line is even re-enabled so no delays should
be experienced.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 3/9] OMAP3: PM: remove serial resume / idle calls from idle path
  2011-06-29  9:04 ` [PATCHv4 3/9] OMAP3: PM: remove serial resume / idle calls from idle path Tero Kristo
@ 2011-06-30 16:50   ` Govindraj
  0 siblings, 0 replies; 22+ messages in thread
From: Govindraj @ 2011-06-30 16:50 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

On Wed, Jun 29, 2011 at 2:34 PM, Tero Kristo <t-kristo@ti.com> wrote:
> This is no longer needed as it will be handled within serial driver itself.
>

Can be marked as tmp same is done with uart runtime

https://patchwork.kernel.org/patch/862332/

--
Thanks,
Govindraj.R

> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> ---
>  arch/arm/mach-omap2/pm34xx.c |   19 -------------------
>  1 files changed, 0 insertions(+), 19 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 89cf027..e626a3d 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -335,18 +335,9 @@ void omap_sram_idle(void)
>                omap3_enable_io_chain();
>        }
>
> -       /* Block console output in case it is on one of the OMAP UARTs */
> -       if (!is_suspending())
> -               if (per_next_state < PWRDM_POWER_ON ||
> -                   core_next_state < PWRDM_POWER_ON)
> -                       if (!console_trylock())
> -                               goto console_still_active;
> -
>        /* PER */
>        if (per_next_state < PWRDM_POWER_ON) {
>                per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
> -               omap_uart_prepare_idle(2);
> -               omap_uart_prepare_idle(3);
>                omap2_gpio_prepare_for_idle(per_going_off);
>                if (per_next_state == PWRDM_POWER_OFF)
>                                omap3_per_save_context();
> @@ -354,8 +345,6 @@ void omap_sram_idle(void)
>
>        /* CORE */
>        if (core_next_state < PWRDM_POWER_ON) {
> -               omap_uart_prepare_idle(0);
> -               omap_uart_prepare_idle(1);
>                if (core_next_state == PWRDM_POWER_OFF) {
>                        omap3_core_save_context();
>                        omap3_cm_save_context();
> @@ -402,8 +391,6 @@ void omap_sram_idle(void)
>                        omap3_sram_restore_context();
>                        omap2_sms_restore_context();
>                }
> -               omap_uart_resume_idle(0);
> -               omap_uart_resume_idle(1);
>                if (core_next_state == PWRDM_POWER_OFF)
>                        omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
>                                               OMAP3430_GR_MOD,
> @@ -417,14 +404,8 @@ void omap_sram_idle(void)
>                omap2_gpio_resume_after_idle();
>                if (per_prev_state == PWRDM_POWER_OFF)
>                        omap3_per_restore_context();
> -               omap_uart_resume_idle(2);
> -               omap_uart_resume_idle(3);
>        }
>
> -       if (!is_suspending())
> -               console_unlock();
> -
> -console_still_active:
>        /* Disable IO-PAD and IO-CHAIN wakeup */
>        if (omap3_has_io_wakeup() &&
>            (per_next_state < PWRDM_POWER_ON ||
> --
> 1.7.4.1
>
>
> Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 2/9] PRCM: Add support for PAD wakeup interrupts
  2011-06-29  9:04 ` [PATCHv4 2/9] PRCM: Add support for PAD wakeup interrupts Tero Kristo
@ 2011-06-30 17:10   ` Govindraj
  2011-07-01 22:03   ` Kevin Hilman
  1 sibling, 0 replies; 22+ messages in thread
From: Govindraj @ 2011-06-30 17:10 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

On Wed, Jun 29, 2011 at 2:34 PM, Tero Kristo <t-kristo@ti.com> wrote:
> PRCM interrupt handler will now parse registered pads to see whether there
> is an active wakeup event. If there is a pending wakeup event, the registered
> ISR will be called.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> ---
>  arch/arm/mach-omap2/prcm.c             |   94 ++++++++++++++++++++++++++++++++
>  arch/arm/plat-omap/include/plat/prcm.h |    5 ++
>  2 files changed, 99 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
> index 794e451..6b603eb 100644
> --- a/arch/arm/mach-omap2/prcm.c
> +++ b/arch/arm/mach-omap2/prcm.c
> @@ -30,6 +30,7 @@
>  #include <plat/common.h>
>  #include <plat/prcm.h>
>  #include <plat/irqs.h>
> +#include <plat/omap_hwmod.h>
>
>  #include "clock.h"
>  #include "clock2xxx.h"
> @@ -40,6 +41,7 @@
>  #include "prm-regbits-24xx.h"
>  #include "prm-regbits-44xx.h"
>  #include "control.h"
> +#include "mux.h"
>
>  void __iomem *prm_base;
>  void __iomem *cm_base;
> @@ -50,6 +52,15 @@ void __iomem *cm2_base;
>  /* Setup for the interrupt handling based on used platform */
>  static struct omap_prcm_irq_setup *irq_setup;
>
> +/* PAD handlers list */
> +struct pad_def {
> +       struct omap_device_pad *pad;
> +       unsigned int irq;
> +       struct list_head node;
> +};
> +
> +static LIST_HEAD(pad_handler_list);
> +
>  static void prcm_irq_ack(struct irq_data *data)
>  {
>        unsigned int prcm_irq = data->irq - OMAP_PRCM_IRQ_BASE;
> @@ -71,6 +82,24 @@ static void prcm_irq_unmask(struct irq_data *data)
>  static struct irq_chip_generic *prcm_irq_chips[OMAP_PRCM_MAX_NR_PENDING_REG];
>
>  /*
> + * Handler for PAD irqs, called from PRCM interrupt handler
> + */
> +static void omap_prcm_handle_pad_irqs(void)
> +{
> +       struct pad_def *def;
> +       u16 val = 0;
> +       list_for_each_entry(def, &pad_handler_list, node) {
> +               /* Read padconf value */
> +               val = omap_mux_read(def->pad->partition,
> +                       def->pad->mux->reg_offset);
> +
> +               /* If pad wakeupevent is active, call registered ISR */
> +               if (val & OMAP3_PADCONF_WAKEUPEVENT0)
> +                       generic_handle_irq(def->irq);
> +       }
> +}
> +
> +/*
>  * PRCM Interrupt Handler
>  *
>  * The PRM_IRQSTATUS_MPU register indicates if there are any pending
> @@ -92,6 +121,9 @@ static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
>        unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG];
>        struct irq_chip *chip = irq_desc_get_chip(desc);
>
> +       /* Handle PAD events first, we don't want to ack them before parse */
> +       omap_prcm_handle_pad_irqs();
> +
>        /*
>         * Loop until all pending irqs are handled, since
>         * generic_handle_irq(), called by prcm_irq_handle_virtirqs()
> @@ -139,6 +171,68 @@ int omap_prcm_event_to_irq(const char *name)
>  }
>
>  /*
> + * Register interrupt handler for a given omap_hwmod_mux. When the PRCM
> + * interrupt handler detects wakeupevent on the corresponding pad, the
> + * ISR will be called.
> + */
> +int omap_prcm_register_pad_irqs(struct omap_hwmod_mux_info *mux,
> +                               unsigned int irq)
> +{
> +       struct pad_def *def;
> +       int i;
> +       u16 val;
> +
> +       if (!mux)
> +               return 0;
> +
> +       for (i = 0; i < mux->nr_pads; i++) {
> +               if (!(mux->pads[i].enable & OMAP_PIN_INPUT))
> +                       continue;
> +

cant be some thing like below considering my pad has entry as [1]

if(!(mux->pads[i].flags & ( OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP))
        continue;


> +               def = kmalloc(sizeof(struct pad_def), GFP_ATOMIC);
> +               if (!def)
> +                       return -ENOMEM;
> +
> +               def->pad = mux->pads + i;
> +               def->irq = irq;
> +
> +               /* Enable pad wakeup */
> +               val = omap_mux_read(def->pad->partition,
> +                       def->pad->mux->reg_offset);
> +               val |= OMAP_WAKEUP_EN;
> +               omap_mux_write(def->pad->partition, val,
> +                       def->pad->mux->reg_offset);


I think all direct read write to mux data can be avoided,

just cant we do

mux->pads[i].idle |= OMAP_WAKEUP_EN;

considering if if I have a uart pad entry for rx as below,

[1]:

{
	.name   = "uart1_rx.uart1_rx",
	.flags  = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
	.enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
	.idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
},




> +
> +               list_add(&def->node, &pad_handler_list);
> +       }
> +       return 0;
> +}
> +
> +/*
> + * Unregister pad irqs associated with a hwmod mux
> + */
> +void omap_prcm_unregister_pad_irqs(struct omap_hwmod_mux_info *mux)
> +{
> +       struct pad_def *def;
> +       int i;
> +       u16 val;
> +
> +       list_for_each_entry(def, &pad_handler_list, node)
> +               for (i = 0; i < mux->nr_pads; i++)
> +                       if (def->pad == mux->pads + i) {
> +                               list_del(&def->node);
> +
> +                               /* Disable pad wakeup */
> +                               val = omap_mux_read(def->pad->partition,
> +                                       def->pad->mux->reg_offset);
> +                               val &= ~OMAP_WAKEUP_EN;

same here.

mux->pads[i].idle &= ~OMAP_WAKEUP_EN;

--
Thanks,
Govindraj.R


> +                               omap_mux_write(def->pad->partition, val,
> +                                       def->pad->mux->reg_offset);
> +                               kfree(def);
> +                       }
> +}
> +
> +/*
>  * Prepare the array of PRCM events corresponding to the current SoC,
>  * and set-up the chained interrupt handler mechanism.
>  */
> diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
> index 205b9b1..7987819 100644
> --- a/arch/arm/plat-omap/include/plat/prcm.h
> +++ b/arch/arm/plat-omap/include/plat/prcm.h
> @@ -66,10 +66,15 @@ struct omap_prcm_irq_setup {
>        int irq;
>  };
>
> +struct omap_hwmod_mux_info;
> +
>  int omap_prcm_event_to_irq(const char *name);
>  int omap_prcm_irq_init(void);
>  void omap_prcm_irq_setup(struct omap_prcm_irq_setup *setup);
>  void omap_prcm_irq_cleanup(void);
> +int omap_prcm_register_pad_irqs(struct omap_hwmod_mux_info *mux,
> +                               unsigned int irq);
> +void omap_prcm_unregister_pad_irqs(struct omap_hwmod_mux_info *mux);
>  u32 omap_prcm_get_reset_sources(void);
>  int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
>                         const char *name);
> --
> 1.7.4.1
>
>
> Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 9/9] OMAP3: PM: Disable / enable PRCM chain interrupts during wakeup from suspend
  2011-06-29  9:05 ` [PATCHv4 9/9] OMAP3: PM: Disable / enable PRCM chain interrupts during wakeup from suspend Tero Kristo
@ 2011-07-01 20:10   ` Kevin Hilman
  0 siblings, 0 replies; 22+ messages in thread
From: Kevin Hilman @ 2011-07-01 20:10 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

Tero Kristo <t-kristo@ti.com> writes:

> This prevents system hang while attempting to access suspended console.

Please add more detail.  Who is accessing console?   This sounds more
like it's masking a UART/console bug.

> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> ---
>  arch/arm/mach-omap2/pm34xx.c |    6 ++++++
>  1 files changed, 6 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index e626a3d..dae0a8a 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -418,6 +418,10 @@ void omap_sram_idle(void)
>  	pwrdm_post_transition();
>  
>  	clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
> +	if (suspend_state != PM_SUSPEND_ON) {
> +		disable_irq(prcm_io_irq);
> +		disable_irq(prcm_wkup_irq);
> +	}

>  }
>  
>  int omap3_can_sleep(void)
> @@ -524,6 +528,8 @@ static void omap3_pm_end(void)
>  	suspend_state = PM_SUSPEND_ON;
>  	omap_uart_enable_irqs(1);
>  	enable_hlt();
> +	enable_irq(prcm_io_irq);
> +	enable_irq(prcm_wkup_irq);
>  	return;
>  }

The re-enable is in ->end(), shouldn't the disable be in ->begin() ?

Kevin



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism
  2011-06-29  9:04 ` [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism Tero Kristo
  2011-06-29 16:53   ` Felipe Balbi
@ 2011-07-01 21:58   ` Kevin Hilman
  1 sibling, 0 replies; 22+ messages in thread
From: Kevin Hilman @ 2011-07-01 21:58 UTC (permalink / raw)
  To: Tero Kristo
  Cc: linux-omap, Thomas Petazzoni, Avinash.H.M, Cousson, Benoit,
	Tony Lindgren, Govindraj.R

Tero Kristo <t-kristo@ti.com> writes:

> Introduce a chained interrupt handler mechanism for the PRCM
> interrupt, so that individual PRCM event can cleanly be handled by
> handlers in separate drivers. We do this by introducing PRCM event
> names, which are then matched to the particular PRCM interrupt bit
> depending on the specific OMAP SoC being used.
>
> arch/arm/mach-omap2/prcm.c implements the chained interrupt mechanism
> itself, with individual PRCM events for OMAP3 and OMAP4 being
> described in arch/arm/mach-omap2/prcm3xxx.c and
> arch/arm/mach-omap2/prcm4xxx.c respectively. At initialization time,
> the set of PRCM events is filtered against the SoC on which we are
> running, keeping only the ones that are actually useful. All the logic
> is written to be generic with regard to OMAP3/OMAP4, even though OMAP3
> has single PRCM event registers and OMAP4 has two PRCM event
> registers.
>
> Patch tested on OMAP3 beagleboard.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Avinash.H.M <avinashhm@ti.com>
> Cc: Kevin Hilman <khilman@ti.com>
> Cc: Cousson, Benoit <b-cousson@ti.com>
> Cc: Tony Lindgren <tony@atomide.com>
> Cc: Govindraj.R <govindraj.raja@ti.com>
> ---
>  arch/arm/mach-omap2/Makefile           |    4 +
>  arch/arm/mach-omap2/pm34xx.c           |  116 ++++++++--------------
>  arch/arm/mach-omap2/prcm.c             |  163 ++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/prcm3xxx.c         |  141 ++++++++++++++++++++++++++
>  arch/arm/mach-omap2/prcm4xxx.c         |  170 ++++++++++++++++++++++++++++++++
>  arch/arm/plat-omap/include/plat/irqs.h |    9 ++-
>  arch/arm/plat-omap/include/plat/prcm.h |   43 ++++++++
>  7 files changed, 569 insertions(+), 77 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/prcm3xxx.c
>  create mode 100644 arch/arm/mach-omap2/prcm4xxx.c
>
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index 5024064..339d2d4 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -39,6 +39,10 @@ AFLAGS_sram242x.o			:=-Wa,-march=armv6
>  AFLAGS_sram243x.o			:=-Wa,-march=armv6
>  AFLAGS_sram34xx.o			:=-Wa,-march=armv7-a
>  
> +# PRCM
> +obj-$(CONFIG_ARCH_OMAP3)                += prcm3xxx.o
> +obj-$(CONFIG_ARCH_OMAP4)                += prcm4xxx.o
> +
>  # Pin multiplexing
>  obj-$(CONFIG_SOC_OMAP2420)		+= mux2420.o
>  obj-$(CONFIG_SOC_OMAP2430)		+= mux2430.o
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 96a7624..89cf027 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -64,6 +64,9 @@ static inline bool is_suspending(void)
>  }
>  #endif
>  
> +static int prcm_io_irq;
> +static int prcm_wkup_irq;
> +
>  /* Scratchpad offsets */
>  #define OMAP343X_TABLE_ADDRESS_OFFSET	   0xc4
>  #define OMAP343X_TABLE_VALUE_OFFSET	   0xc0
> @@ -240,75 +243,16 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs)
>  	return c;
>  }
>  
> -static int _prcm_int_handle_wakeup(void)
> +static irqreturn_t _prcm_int_handle_wakeup(int irq, void *unused)
>  {
> -	int c;
> -
> -	c = prcm_clear_mod_irqs(WKUP_MOD, 1);
> -	c += prcm_clear_mod_irqs(CORE_MOD, 1);
> -	c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1);
> +	prcm_clear_mod_irqs(WKUP_MOD, 1);
> +	prcm_clear_mod_irqs(CORE_MOD, 1);
> +	prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1);
>  	if (omap_rev() > OMAP3430_REV_ES1_0) {
> -		c += prcm_clear_mod_irqs(CORE_MOD, 3);
> -		c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1);
> +		prcm_clear_mod_irqs(CORE_MOD, 3);
> +		prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1);
>  	}

Maybe we should keep the various 'c += ' counting in there, and only
return IRQ_HANDLED if (c > 0) ?

> -	return c;
> -}

[...]

> diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
> index 6be1438..794e451 100644
> --- a/arch/arm/mach-omap2/prcm.c
> +++ b/arch/arm/mach-omap2/prcm.c
> @@ -23,6 +23,8 @@
>  #include <linux/clk.h>
>  #include <linux/io.h>
>  #include <linux/delay.h>
> +#include <linux/irq.h>
> +#include <linux/slab.h>
>  
>  #include <mach/system.h>
>  #include <plat/common.h>
> @@ -45,6 +47,167 @@ void __iomem *cm2_base;
>  
>  #define MAX_MODULE_ENABLE_WAIT		100000
>  
> +/* Setup for the interrupt handling based on used platform */
> +static struct omap_prcm_irq_setup *irq_setup;
> +
> +static void prcm_irq_ack(struct irq_data *data)
> +{
> +	unsigned int prcm_irq = data->irq - OMAP_PRCM_IRQ_BASE;
> +	irq_setup->ack_event(prcm_irq);
> +}
> +
> +static void prcm_irq_mask(struct irq_data *data)
> +{
> +	unsigned int prcm_irq = data->irq - OMAP_PRCM_IRQ_BASE;
> +	irq_setup->mask_event(prcm_irq);
> +}
> +
> +static void prcm_irq_unmask(struct irq_data *data)
> +{
> +	unsigned int prcm_irq = data->irq - OMAP_PRCM_IRQ_BASE;
> +	irq_setup->unmask_event(prcm_irq);
> +}

In moving to generic IRQ chip, it's all of the ack/mask/unmask functions
here that I want to get rid of, since the generic IRQ chip layer can do
all of this for you.

Instead, we can just pass in the register address(es) to the generic IRQ
chip, and use the generic irq_chip ack/mask/unmask functions.  This is
how the INTC code does it.

So, rather than have ack/mask/umask function in the prcm[34]xxx.c files,
and in prcm.c file, you can remove them all.  Instead, in the
prcm[34]xxxx files, just define the ack and mask registers (e.g. for OMAP3):

 static struct omap_prcm_irq_setup __initdata omap3_prcm_irq_setup = {
-	.mask_event = omap3_prcm_mask_event,
-	.unmask_event = omap3_prcm_unmask_event,
-	.ack_event = omap3_prcm_ack_event,
+	.ack = OMAP34XX_PRM_REGADDR(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET),
+	.mask = OMAP34XX_PRM_REGADDR(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET),
 	.pending_events = omap3_prcm_pending_events,
 	.irqs = omap_prcm_3xxx_irqs,
 	.num_irqs = ARRAY_SIZE(omap_prcm_3xxx_irqs),
 	.irq = INT_34XX_PRCM_MPU_IRQ,
 };

then...

> +/*
> + * Prepare the array of PRCM events corresponding to the current SoC,
> + * and set-up the chained interrupt handler mechanism.
> + */
> +int __init omap_prcm_irq_init(void)
> +{
> +	int i;
> +	struct irq_chip_generic *gc;
> +	struct irq_chip_type *ct;
> +	u32 mask[2] = { 0, 0 };
> +	int offset;
> +	int max_irq = 0;
> +
> +	for (i = 0; i < irq_setup->num_irqs; i++)
> +		if (omap_chip_is(irq_setup->irqs[i].omap_chip)) {
> +			offset = irq_setup->irqs[i].offset;
> +			if (offset < 32)
> +				mask[0] |= 1 << offset;
> +			else
> +				mask[1] |= 1 << (offset - 32);
> +			if (offset > max_irq)
> +				max_irq = offset;
> +		}
> +
> +	irq_set_chained_handler(irq_setup->irq, prcm_irq_handler);
> +
> +	for (i = 0; i <= max_irq / 32; i++) {
> +		gc = irq_alloc_generic_chip("PRCM", 1,
> +			OMAP_PRCM_IRQ_BASE + i * 32, NULL, handle_level_irq);
> +
> +		ct = gc->chip_types;
> +		ct->chip.irq_ack = prcm_irq_ack;
> +		ct->chip.irq_mask = prcm_irq_mask;
> +		ct->chip.irq_unmask = prcm_irq_unmask;

...use the generic IRQ functions

		ct->chip.irq_ack = irq_gc_ack;
		ct->chip.irq_mask = irq_gc_mask_set_bit;
		ct->chip.irq_unmask = irq_gc_mask_clr_bit;

and pass in the register offsets configured in the SoC-specific code:

		ct->regs.ack = irq_setup->ack + (i << 2);
		ct->regs.mask = irq_setup->mask + (i << 2);

> +		irq_setup_generic_chip(gc, mask[i], 0, IRQ_NOREQUEST, 0);
> +		prcm_irq_chips[i] = gc;
> +	}
> +	return 0;
> +}
> +


[...]

> diff --git a/arch/arm/mach-omap2/prcm3xxx.c b/arch/arm/mach-omap2/prcm3xxx.c
> new file mode 100644
> index 0000000..5671650
> --- /dev/null
> +++ b/arch/arm/mach-omap2/prcm3xxx.c
> @@ -0,0 +1,141 @@
> +/*
> + * linux/arch/arm/mach-omap2/prcm3xxx.c

Minor: please remove the filename from the header.  Files move around
and these comments never get updated.

Also, I know you inherited this from previous code, but we probably
don't need new prcm*.c files.  All this IRQ stuff is part of the PRM
(not CM) and belongs in prm2xxx_3xxx.c and prm4xxx.c.

Kevin

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 2/9] PRCM: Add support for PAD wakeup interrupts
  2011-06-29  9:04 ` [PATCHv4 2/9] PRCM: Add support for PAD wakeup interrupts Tero Kristo
  2011-06-30 17:10   ` Govindraj
@ 2011-07-01 22:03   ` Kevin Hilman
  1 sibling, 0 replies; 22+ messages in thread
From: Kevin Hilman @ 2011-07-01 22:03 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

Tero Kristo <t-kristo@ti.com> writes:

> PRCM interrupt handler will now parse registered pads to see whether there
> is an active wakeup event. If there is a pending wakeup event, the registered
> ISR will be called.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

This patch adds a new, duplicate mapping of pad-to-IRQ which is already
contained in each omap_hwmod.  See my comments on the v3 version of this
patch[1] which describes how I think this should be handled.

Kevin

[1] http://marc.info/?l=linux-omap&m=130895127714616&w=2

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 6/9] OMAP device: change pr_warnings to pr_debugs
  2011-06-29  9:05 ` [PATCHv4 6/9] OMAP device: change pr_warnings to pr_debugs Tero Kristo
@ 2011-07-01 22:05   ` Kevin Hilman
  0 siblings, 0 replies; 22+ messages in thread
From: Kevin Hilman @ 2011-07-01 22:05 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

Tero Kristo <t-kristo@ti.com> writes:

> Prevents a hang when omap_device would want to print something for
> serial console device while enabling / disabling its clocks.

hang is still there if you boot with 'debug' on the cmdline.

This needs a fix in the UART driver using console locking.

This should be marked as 'TEMP' also as this should be fixed in the UART
drivers runtime PM adaptation.

Kevin

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 7/9] OMAP: hwmod: enable / disable pad wakeups for a module dynamically
  2011-06-29  9:05 ` [PATCHv4 7/9] OMAP: hwmod: enable / disable pad wakeups for a module dynamically Tero Kristo
@ 2011-07-01 22:18   ` Kevin Hilman
  2011-07-02 11:10     ` Govindraj
  0 siblings, 1 reply; 22+ messages in thread
From: Kevin Hilman @ 2011-07-01 22:18 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap, Paul Walmsley

Tero Kristo <t-kristo@ti.com> writes:

> PRCM chain interrupt registration is done now as part of
> omap_hwmod_enable_wakeup() and omap_hwmod_disable_wakeup() calls. This
> allows module ISR:s to be called when the module is idle but an IO_PAD
> event is detected on the module input pads.

These functions are the enable/disable for module-level wakeups, you
need to use the proposed enable/disable functions for IO ring wakeups as
proposed in the patch from Govindraj[1].

I'm hoping that patch will be queued for v3.1, but will wait for Paul's
comments on that patch.

Kevin

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCHv4 7/9] OMAP: hwmod: enable / disable pad wakeups for a module dynamically
  2011-07-01 22:18   ` Kevin Hilman
@ 2011-07-02 11:10     ` Govindraj
  0 siblings, 0 replies; 22+ messages in thread
From: Govindraj @ 2011-07-02 11:10 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Tero Kristo, linux-omap, Paul Walmsley

On Sat, Jul 2, 2011 at 3:48 AM, Kevin Hilman <khilman@ti.com> wrote:
> Tero Kristo <t-kristo@ti.com> writes:
>
>> PRCM chain interrupt registration is done now as part of
>> omap_hwmod_enable_wakeup() and omap_hwmod_disable_wakeup() calls. This
>> allows module ISR:s to be called when the module is idle but an IO_PAD
>> event is detected on the module input pads.
>
> These functions are the enable/disable for module-level wakeups, you
> need to use the proposed enable/disable functions for IO ring wakeups as
> proposed in the patch from Govindraj[1].
>


Posted a new version rebased on 3.0-rc5

https://patchwork.kernel.org/patch/940332/
https://patchwork.kernel.org/patch/940322/

--
Thanks,
Govindraj.R


> I'm hoping that patch will be queued for v3.1, but will wait for Paul's
> comments on that patch.
>
> Kevin
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2011-07-02 11:10 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-29  9:04 [PATCHv4 0/9] PRCM chain interrupt handling Tero Kristo
2011-06-29  9:04 ` [PATCHv4 1/9] omap: prcm: switch to a chained IRQ handler mechanism Tero Kristo
2011-06-29 16:53   ` Felipe Balbi
2011-06-29 16:54     ` Felipe Balbi
2011-06-30  5:51     ` Tero Kristo
2011-06-30  9:11       ` Felipe Balbi
2011-07-01 21:58   ` Kevin Hilman
2011-06-29  9:04 ` [PATCHv4 2/9] PRCM: Add support for PAD wakeup interrupts Tero Kristo
2011-06-30 17:10   ` Govindraj
2011-07-01 22:03   ` Kevin Hilman
2011-06-29  9:04 ` [PATCHv4 3/9] OMAP3: PM: remove serial resume / idle calls from idle path Tero Kristo
2011-06-30 16:50   ` Govindraj
2011-06-29  9:04 ` [PATCHv4 4/9] TEMP: OMAP3: Serial: Made serial to work properly with PRCM chain handler Tero Kristo
2011-06-29  9:04 ` [PATCHv4 5/9] TEMP: Serial: Added mux support Tero Kristo
2011-06-29  9:05 ` [PATCHv4 6/9] OMAP device: change pr_warnings to pr_debugs Tero Kristo
2011-07-01 22:05   ` Kevin Hilman
2011-06-29  9:05 ` [PATCHv4 7/9] OMAP: hwmod: enable / disable pad wakeups for a module dynamically Tero Kristo
2011-07-01 22:18   ` Kevin Hilman
2011-07-02 11:10     ` Govindraj
2011-06-29  9:05 ` [PATCHv4 8/9] TEMP: OMAP: serial: remove padconf hacks Tero Kristo
2011-06-29  9:05 ` [PATCHv4 9/9] OMAP3: PM: Disable / enable PRCM chain interrupts during wakeup from suspend Tero Kristo
2011-07-01 20:10   ` Kevin Hilman

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.