All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv5 00/11] PRCM chain handler
@ 2011-07-05 10:27 Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism Tero Kristo
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 UTC (permalink / raw)
  To: linux-omap

Changes compared to previous version:

- rebased on top of latest PM branch
- sparse interrupt numbering in use (thanks Felipe)
- removed duplicate pad mapping as proposed by Kevin
  * io pad parsing done now in a support function provided by omap_hwmod
  * see patch 4
- using Govindraj's ioring support functions for mux
  * patches 2 + 3 only added as reference and because this set needs those
- tagged a couple of more patches as TEMP, these are just for testing purposes
  * also changed suspend irq disable / enable logic a bit
- generic irq chip used more properly now, dropped most of the support funcs

Tested again on omap3-beagle:
- suspend / resume with retention -> ok
- cpuidle with retention -> ok

Off-mode tested also, kind of works but hangs eventually. This happens with
plain PM branch also, so it is not caused by this set.

On top of commit 40d10207b5389184333bacb786d27036cbcee500 off-mode was
still functional, so it would seem like some late patch has broken something.

-Tero


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


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

* [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  2011-07-05 11:18   ` Felipe Balbi
                     ` (3 more replies)
  2011-07-05 10:27 ` [PATCHv5 02/11] OMAP2+: hwmod: Add API to enable IO ring wakeup Tero Kristo
                   ` (9 subsequent siblings)
  10 siblings, 4 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 UTC (permalink / raw)
  To: linux-omap
  Cc: Thomas Petazzoni, Avinash.H.M, Kevin Hilman, Cousson, Benoit,
	Tony Lindgren, Govindraj.R, Felipe Balbi

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>
Cc: Felipe Balbi <balbi@ti.com>
---
 arch/arm/mach-omap2/Makefile           |    4 +
 arch/arm/mach-omap2/pm34xx.c           |  108 ++++++++--------------
 arch/arm/mach-omap2/prcm.c             |  158 ++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prcm3xxx.c         |  112 ++++++++++++++++++++++
 arch/arm/mach-omap2/prcm4xxx.c         |  137 +++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/prcm.h |   46 +++++++++
 6 files changed, 495 insertions(+), 70 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 027958c..8ee70ed 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 3279569..d80bf8b 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;
+
 /* pm34xx errata defined in pm.h */
 u16 pm34xx_errata;
 
@@ -235,7 +238,7 @@ 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;
 
@@ -247,64 +250,9 @@ static int _prcm_int_handle_wakeup(void)
 		c += 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;
+	if (c)
+		return IRQ_HANDLED;
+	return IRQ_NONE;
 }
 
 static void omap34xx_do_sram_idle(unsigned long save_state)
@@ -854,20 +802,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);
@@ -875,7 +838,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");
@@ -924,14 +887,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..e7d602c 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,162 @@ 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 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(irq_setup->base_irq + 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 irq_setup->base_irq + 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);
+
+	irq_setup->base_irq = irq_alloc_descs(-1, 0, OMAP_PRCM_NR_IRQS, 0);
+
+	if (irq_setup->base_irq < 0) {
+		pr_err("PRCM: failed to allocate irq descs\n");
+		irq_set_chained_handler(irq_setup->irq, NULL);
+		return irq_setup->base_irq;
+	}
+
+	for (i = 0; i <= max_irq / 32; i++) {
+		gc = irq_alloc_generic_chip("PRCM", 1,
+			irq_setup->base_irq + i * 32, NULL, handle_level_irq);
+
+		ct = gc->chip_types;
+		ct->chip.irq_ack = irq_gc_ack;
+		ct->chip.irq_mask = irq_gc_mask_clr_bit;
+		ct->chip.irq_unmask = irq_gc_mask_set_bit;
+
+		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;
+}
+
+/*
+ * 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);
+
+	irq_free_descs(irq_setup->base_irq, OMAP_PRCM_NR_IRQS);
+}
+
+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..dea8cca
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm3xxx.c
@@ -0,0 +1,112 @@
+/*
+ * 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 <plat/io.h>
+
+#include "prm-regbits-24xx.h"
+
+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 = {
+	.ack = (u32)OMAP3430_PRM_IRQSTATUS_MPU,
+	.mask = (u32)OMAP3430_PRM_IRQENABLE_MPU,
+	.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_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..b1f9201
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm4xxx.c
@@ -0,0 +1,137 @@
+/*
+ * 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 <plat/io.h>
+
+#include "prcm44xx.h"
+#include "prm44xx.h"
+
+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 = {
+	.ack = (u32)OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST,
+			OMAP4_PRM_IRQSTATUS_MPU_OFFSET),
+	.mask = (u32)OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST,
+			OMAP4_PRM_IRQENABLE_MPU_OFFSET),
+	.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_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/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
index 267f43b..76acbb7 100644
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ b/arch/arm/plat-omap/include/plat/prcm.h
@@ -27,6 +27,52 @@
 #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
+
+/* 64 interrupts needed on OMAP4, 32 on OMAP3 */
+#define OMAP_PRCM_NR_IRQS		64
+
+/* Setup for the PRCM interrupt handler */
+struct omap_prcm_irq_setup {
+	void (*pending_events)(unsigned long *);
+	u32 ack;
+	u32 mask;
+	struct omap_prcm_irq *irqs;
+	int num_irqs;
+	int irq;
+	int base_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] 23+ messages in thread

* [PATCHv5 02/11] OMAP2+: hwmod: Add API to enable IO ring wakeup.
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 03/11] OMAP2+: hwmod: Add API to check IO PAD wakeup status Tero Kristo
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 UTC (permalink / raw)
  To: linux-omap; +Cc: R, Govindraj

From: R, Govindraj <govindraj.raja@ti.com>

Add API to enable IO pad wakeup capability based on mux dynamic pad and
wake_up enable flag available from hwmod_mux initialization.

Use the wakeup_enable flag and enable wakeup capability
for the given pads. Wakeup capability will be enabled/disabled
during hwmod idle transition based on whether wakeup_flag is
set or cleared.

Map the enable/disable pad wakeup API's to hwmod_wakeup_enable/disable.

Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c |   59 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 51a13f3..17fa1ab 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1952,6 +1952,34 @@ static int __init omap_hwmod_setup_all(void)
 core_initcall(omap_hwmod_setup_all);
 
 /**
+ * omap_hwmod_set_ioring_wakeup - enable io pad wakeup flag.
+ * @oh: struct omap_hwmod *
+ * @set: bool value indicating to set or clear wakeup status.
+ *
+ * Set or Clear wakeup flag for the io_pad.
+ */
+static int omap_hwmod_set_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+	struct omap_device_pad *pad;
+	int ret = -EINVAL, j;
+
+	if (oh->mux && oh->mux->enabled) {
+		for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
+			pad = oh->mux->pads_dynamic[j];
+			if (pad->flags & OMAP_DEVICE_PAD_WAKEUP) {
+				if (set_wake)
+					pad->idle |= OMAP_WAKEUP_EN;
+				else
+					pad->idle &= ~OMAP_WAKEUP_EN;
+				ret = 0;
+			}
+		}
+	}
+
+	return ret;
+}
+
+/**
  * omap_hwmod_enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
  *
@@ -2265,6 +2293,35 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
 {
 	return _del_initiator_dep(oh, init_oh);
 }
+/**
+ * omap_hwmod_enable_ioring_wakeup - Set wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * set wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh)
+{
+	/* Enable pad wake-up capability */
+	return omap_hwmod_set_ioring_wakeup(oh, true);
+}
+
+/**
+ * omap_hwmod_disable_ioring_wakeup - Clear wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * clear wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_disable_ioring_wakeup(struct omap_hwmod *oh)
+{
+	/* Disable pad wakeup capability */
+	return omap_hwmod_set_ioring_wakeup(oh, false);
+}
 
 /**
  * omap_hwmod_enable_wakeup - allow device to wake up the system
@@ -2291,6 +2348,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_enable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	omap_hwmod_enable_ioring_wakeup(oh);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
@@ -2321,6 +2379,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_disable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	omap_hwmod_disable_ioring_wakeup(oh);
 	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] 23+ messages in thread

* [PATCHv5 03/11] OMAP2+: hwmod: Add API to check IO PAD wakeup status
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 02/11] OMAP2+: hwmod: Add API to enable IO ring wakeup Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 04/11] OMAP2+: hwmod: add support for PAD wakeup interrupts Tero Kristo
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 UTC (permalink / raw)
  To: linux-omap; +Cc: R, Govindraj

From: R, Govindraj <govindraj.raja@ti.com>

Add API to determine IO-PAD wakeup event status for a given
hwmod dynamic_mux pad.

Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
 arch/arm/mach-omap2/mux.c                    |   30 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/mux.h                    |   13 +++++++++++
 arch/arm/mach-omap2/omap_hwmod.c             |    7 ++++++
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    1 +
 4 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index c7fb22a..50ee806 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -351,6 +351,36 @@ err1:
 	return NULL;
 }
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux:		Pads for a hwmod
+ *
+ * Gets the wakeup status of given pad from omap-hwmod.
+ * Returns true if wakeup event is set for pad else false
+ * if wakeup is not occured or pads are not avialable.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+	int i;
+	unsigned int val;
+	u8 ret = false;
+
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];
+
+		if (pad->flags & OMAP_DEVICE_PAD_WAKEUP) {
+			val = omap_mux_read(pad->partition,
+					pad->mux->reg_offset);
+			if (val & OMAP_WAKEUP_EVENT) {
+				ret = true;
+				break;
+			}
+		}
+	}
+
+	return ret;
+}
+
 /* Assumes the calling function takes care of locking */
 void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
 {
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 2132308..8b2150a 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
  */
 void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux:		Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux);
 #else
 
+static inline bool
+omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+	return 0;
+}
+
 static inline int omap_mux_init_gpio(int gpio, int val)
 {
 	return 0;
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 17fa1ab..0dd48ee 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2596,3 +2596,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
 
 	return 0;
 }
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+	if (oh && oh->mux)
+		return omap_hwmod_mux_get_wake_status(oh->mux);
+	return -EINVAL;
+}
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 7df9fa2..8e5025c 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -612,6 +612,7 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out
-- 
1.7.4.1


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


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

* [PATCHv5 04/11] OMAP2+: hwmod: add support for PAD wakeup interrupts
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
                   ` (2 preceding siblings ...)
  2011-07-05 10:27 ` [PATCHv5 03/11] OMAP2+: hwmod: Add API to check IO PAD wakeup status Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  2011-07-22 23:04   ` Kevin Hilman
  2011-07-05 10:27 ` [PATCHv5 05/11] TEMP: OMAP3: pm: remove serial resume / idle calls from idle path Tero Kristo
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 UTC (permalink / raw)
  To: linux-omap

OMAP hwmod now provides a service routine to parse pending wakeup events
and to call registered ISR whenever active wakeups are detected. This
routine is called directly from PRCM interrupt handler.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c             |   19 +++++++++++++++++++
 arch/arm/mach-omap2/prcm.c                   |    4 ++++
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    1 +
 3 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 0dd48ee..3f3e22d 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -135,6 +135,7 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
 
 #include <plat/common.h>
 #include <plat/cpu.h>
@@ -2324,6 +2325,24 @@ int omap_hwmod_disable_ioring_wakeup(struct omap_hwmod *oh)
 }
 
 /**
+ * omap_hwmod_mux_handle_irq - Process pad wakeup irqs.
+ *
+ * Checks every hwmod for every wakeup capable pad to see if there is an
+ * active wakeup event. If this is the case, call the corresponding ISR.
+ */
+void omap_hwmod_mux_handle_irq(void)
+{
+	struct omap_hwmod *oh;
+
+	list_for_each_entry(oh, &omap_hwmod_list, node) {
+		if (!oh->mux || !oh->mux->enabled)
+			continue;
+		if (omap_hwmod_mux_get_wake_status(oh->mux))
+			generic_handle_irq(oh->mpu_irqs[0].irq);
+	}
+}
+
+/**
  * omap_hwmod_enable_wakeup - allow device to wake up the system
  * @oh: struct omap_hwmod *
  *
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index e7d602c..17d3d85 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"
@@ -74,6 +75,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_hwmod_mux_handle_irq();
+
 	/*
 	 * Loop until all pending irqs are handled, since
 	 * generic_handle_irq(), called by prcm_irq_handle_virtirqs()
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 8e5025c..076fa25 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -601,6 +601,7 @@ int omap_hwmod_set_clockact_none(struct omap_hwmod *oh);
 
 int omap_hwmod_enable_wakeup(struct omap_hwmod *oh);
 int omap_hwmod_disable_wakeup(struct omap_hwmod *oh);
+void omap_hwmod_mux_handle_irq(void);
 
 int omap_hwmod_for_each_by_class(const char *classname,
 				 int (*fn)(struct omap_hwmod *oh,
-- 
1.7.4.1


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


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

* [PATCHv5 05/11] TEMP: OMAP3: pm: remove serial resume / idle calls from idle path
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
                   ` (3 preceding siblings ...)
  2011-07-05 10:27 ` [PATCHv5 04/11] OMAP2+: hwmod: add support for PAD wakeup interrupts Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  2011-07-22 23:51   ` Felipe Balbi
  2011-07-05 10:27 ` [PATCHv5 06/11] TEMP: OMAP3: serial: made serial to work properly with PRCM chain handler Tero Kristo
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 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 d80bf8b..d45e7ad 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -315,18 +315,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();
@@ -334,8 +325,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();
@@ -380,8 +369,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,
@@ -395,14 +382,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] 23+ messages in thread

* [PATCHv5 06/11] TEMP: OMAP3: serial: made serial to work properly with PRCM chain handler
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
                   ` (4 preceding siblings ...)
  2011-07-05 10:27 ` [PATCHv5 05/11] TEMP: OMAP3: pm: remove serial resume / idle calls from idle path Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 07/11] TEMP: serial: added mux support Tero Kristo
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 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] 23+ messages in thread

* [PATCHv5 07/11] TEMP: serial: added mux support
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
                   ` (5 preceding siblings ...)
  2011-07-05 10:27 ` [PATCHv5 06/11] TEMP: OMAP3: serial: made serial to work properly with PRCM chain handler Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 08/11] TEMP: OMAP device: change pr_warnings to pr_debugs Tero Kristo
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 UTC (permalink / raw)
  To: linux-omap

Just for PRCM chain handler testing purposes. This should be replaced with
a proper implementation.

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

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 067a86b..ff973b4 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -851,17 +851,84 @@ 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_MUX_MODE0)
+#define OMAP3_SERIAL_MUX_IN_PD (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0)
+#define OMAP3_SERIAL_MUX_IN (OMAP_PIN_INPUT | OMAP_MUX_MODE0)
+#define OMAP3_SERIAL_MUX_OUT (OMAP_PIN_OUTPUT | 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 SERIAL_DISABLED OMAP_MUX_MODE7
+
+#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, SERIAL_DISABLED, },
+	{ "uart1_rts.uart1_rts", OMAP3_SERIAL_MUX_OUT, SERIAL_DISABLED, },
+	{ "uart1_rx.uart1_rx", OMAP3_SERIAL_MUX_IN, SERIAL_DISABLED, },
+	{ "uart1_tx.uart1_tx", OMAP3_SERIAL_MUX_OUT, SERIAL_DISABLED, },
+	{ "uart2_cts.uart2_cts", OMAP3_SERIAL_MUX_IN,
+		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", SERIAL_DISABLED, OMAP4_SERIAL_MUX_IN, },
+	{ "uart4_tx.uart4_tx", SERIAL_DISABLED, 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;
+			pads[i].idle = 0;
+			pads[i].flags = 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 != SERIAL_DISABLED)
+				bdata.pads_cnt++;
+			if (pads[i].enable & OMAP_PIN_INPUT) {
+				pads[i].flags = OMAP_DEVICE_PAD_REMUX |
+					OMAP_DEVICE_PAD_WAKEUP;
+			}
+			pads[i].idle = pads[i].enable;
+		}
+		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] 23+ messages in thread

* [PATCHv5 08/11] TEMP: OMAP device: change pr_warnings to pr_debugs
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
                   ` (6 preceding siblings ...)
  2011-07-05 10:27 ` [PATCHv5 07/11] TEMP: serial: added mux support Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 09/11] TEMP: OMAP: serial: remove padconf hacks Tero Kristo
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 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 9a02d95..9a71751 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] 23+ messages in thread

* [PATCHv5 09/11] TEMP: OMAP: serial: remove padconf hacks
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
                   ` (7 preceding siblings ...)
  2011-07-05 10:27 ` [PATCHv5 08/11] TEMP: OMAP device: change pr_warnings to pr_debugs Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 10/11] TEMP: OMAP3: pm: disable / enable PRCM chain interrupts during wakeup from suspend Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 11/11] OMAP3: pm: do not enable PRCM MPU interrupts manually Tero Kristo
  10 siblings, 0 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 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 ff973b4..c94f87d 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] 23+ messages in thread

* [PATCHv5 10/11] TEMP: OMAP3: pm: disable / enable PRCM chain interrupts during wakeup from suspend
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
                   ` (8 preceding siblings ...)
  2011-07-05 10:27 ` [PATCHv5 09/11] TEMP: OMAP: serial: remove padconf hacks Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  2011-07-05 10:27 ` [PATCHv5 11/11] OMAP3: pm: do not enable PRCM MPU interrupts manually Tero Kristo
  10 siblings, 0 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 UTC (permalink / raw)
  To: linux-omap

This prevents system hang while attempting to access suspended console. Should
most likely be fixed with proper console locking.

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

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index d45e7ad..34feff4 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -494,6 +494,8 @@ static int omap3_pm_begin(suspend_state_t state)
 	disable_hlt();
 	suspend_state = state;
 	omap_uart_enable_irqs(0);
+	disable_irq(prcm_io_irq);
+	disable_irq(prcm_wkup_irq);
 	return 0;
 }
 
@@ -502,6 +504,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] 23+ messages in thread

* [PATCHv5 11/11] OMAP3: pm: do not enable PRCM MPU interrupts manually
  2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
                   ` (9 preceding siblings ...)
  2011-07-05 10:27 ` [PATCHv5 10/11] TEMP: OMAP3: pm: disable / enable PRCM chain interrupts during wakeup from suspend Tero Kristo
@ 2011-07-05 10:27 ` Tero Kristo
  10 siblings, 0 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 10:27 UTC (permalink / raw)
  To: linux-omap

This is handled automatically by the PRCM chain interrupt mechanism now.

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

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 34feff4..8b05f14 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -618,10 +618,6 @@ static void __init prcm_setup_regs(void)
 			  OMAP3430_GRPSEL_GPT1_MASK |
 			  OMAP3430_GRPSEL_GPT12_MASK,
 			  WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
-	/* For some reason IO doesn't generate wakeup event even if
-	 * it is selected to mpu wakeup goup */
-	omap2_prm_write_mod_reg(OMAP3430_IO_EN_MASK | OMAP3430_WKUP_EN_MASK,
-			  OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 
 	/* Enable PM_WKEN to support DSS LPR */
 	omap2_prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK,
-- 
1.7.4.1


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


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

* Re: [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism
  2011-07-05 10:27 ` [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism Tero Kristo
@ 2011-07-05 11:18   ` Felipe Balbi
  2011-07-05 11:32     ` Tero Kristo
  2011-07-15 13:23   ` Govindraj
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 23+ messages in thread
From: Felipe Balbi @ 2011-07-05 11:18 UTC (permalink / raw)
  To: Tero Kristo
  Cc: linux-omap, Thomas Petazzoni, Avinash.H.M, Kevin Hilman, Cousson,
	Benoit, Tony Lindgren, Govindraj.R, Felipe Balbi

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

Hi,

On Tue, Jul 05, 2011 at 01:27:47PM +0300, Tero Kristo wrote:
> @@ -854,20 +802,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);

IRQF_DISABLED shouldn't be used anymore ;-)

<linux/interrupt.h>:

 45  * IRQF_DISABLED - keep irqs disabled when calling the action handler.
 46  *                 DEPRECATED. This flag is a NOOP and scheduled to be removed


-- 
balbi

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

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

* Re: [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism
  2011-07-05 11:18   ` Felipe Balbi
@ 2011-07-05 11:32     ` Tero Kristo
  2011-07-05 11:33       ` Felipe Balbi
  0 siblings, 1 reply; 23+ messages in thread
From: Tero Kristo @ 2011-07-05 11:32 UTC (permalink / raw)
  To: Balbi, Felipe
  Cc: linux-omap, Thomas Petazzoni, Mahadeva, Avinash, Hilman, Kevin,
	Cousson, Benoit, Tony Lindgren, R, Govindraj

On Tue, 2011-07-05 at 13:18 +0200, Balbi, Felipe wrote:
> Hi,
> 
> On Tue, Jul 05, 2011 at 01:27:47PM +0300, Tero Kristo wrote:
> > @@ -854,20 +802,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);
> 
> IRQF_DISABLED shouldn't be used anymore ;-)

Oh man, well that is easy to remove as it doesn't do anything. Should I
send a new version of the set for this? :P Kevin's call I guess.

I just tried the set without this flag and yes it still works. :)

> 
> <linux/interrupt.h>:
> 
>  45  * IRQF_DISABLED - keep irqs disabled when calling the action handler.
>  46  *                 DEPRECATED. This flag is a NOOP and scheduled to be removed
> 
> 



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


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

* Re: [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism
  2011-07-05 11:32     ` Tero Kristo
@ 2011-07-05 11:33       ` Felipe Balbi
  0 siblings, 0 replies; 23+ messages in thread
From: Felipe Balbi @ 2011-07-05 11:33 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: 1158 bytes --]

On Tue, Jul 05, 2011 at 02:32:18PM +0300, Tero Kristo wrote:
> On Tue, 2011-07-05 at 13:18 +0200, Balbi, Felipe wrote:
> > Hi,
> > 
> > On Tue, Jul 05, 2011 at 01:27:47PM +0300, Tero Kristo wrote:
> > > @@ -854,20 +802,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);
> > 
> > IRQF_DISABLED shouldn't be used anymore ;-)
> 
> Oh man, well that is easy to remove as it doesn't do anything. Should I
> send a new version of the set for this? :P Kevin's call I guess.

yeah, Kevin's call :-)

> I just tried the set without this flag and yes it still works. :)

Good :-)

-- 
balbi

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

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

* Re: [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism
  2011-07-05 10:27 ` [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism Tero Kristo
  2011-07-05 11:18   ` Felipe Balbi
@ 2011-07-15 13:23   ` Govindraj
  2011-07-15 16:40   ` Todd Poynor
  2011-07-22 22:58   ` Kevin Hilman
  3 siblings, 0 replies; 23+ messages in thread
From: Govindraj @ 2011-07-15 13:23 UTC (permalink / raw)
  To: Tero Kristo
  Cc: linux-omap, Thomas Petazzoni, Avinash.H.M, Kevin Hilman, Cousson,
	Benoit, Tony Lindgren, Govindraj.R, Felipe Balbi

On Tue, Jul 5, 2011 at 3:57 PM, Tero Kristo <t-kristo@ti.com> wrote:
> 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>
> Cc: Felipe Balbi <balbi@ti.com>
> ---
>  arch/arm/mach-omap2/Makefile           |    4 +
>  arch/arm/mach-omap2/pm34xx.c           |  108 ++++++++--------------
>  arch/arm/mach-omap2/prcm.c             |  158 ++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/prcm3xxx.c         |  112 ++++++++++++++++++++++
>  arch/arm/mach-omap2/prcm4xxx.c         |  137 +++++++++++++++++++++++++++
>  arch/arm/plat-omap/include/plat/prcm.h |   46 +++++++++
>  6 files changed, 495 insertions(+), 70 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/prcm3xxx.c
>  create mode 100644 arch/arm/mach-omap2/prcm4xxx.c
>

[..]

> +       if (irq_setup->base_irq < 0) {
> +               pr_err("PRCM: failed to allocate irq descs\n");
> +               irq_set_chained_handler(irq_setup->irq, NULL);
> +               return irq_setup->base_irq;
> +       }
> +
> +       for (i = 0; i <= max_irq / 32; i++) {
> +               gc = irq_alloc_generic_chip("PRCM", 1,
> +                       irq_setup->base_irq + i * 32, NULL, handle_level_irq);
> +
> +               ct = gc->chip_types;
> +               ct->chip.irq_ack = irq_gc_ack;


With patch [1] already part of 3.0-rc7 Mainline.

irq_gc_ack needs to be changed as below.

ct->chip.irq_ack = irq_gc_ack_set_bit;

I dropped tmp patches from v5 and picked rest of v5 applied
on wip-runtime patches and tested same.

Most of the things worked fine on 3430SDP
System wide suspend (with console_suspend)
retention and off-mode.

I have hosted a branch with the same if some else
is interested in testing.

[rc7 + wip_uart runtime patches + irq_chaining patches]

git://gitorious.org/runtime_3-0/runtime_3-0.git
Branch: wip_irqchn

feel free to add,

Acked-by: Govindraj.R <govindraj.raja@ti.com>
Tested-by: Govindraj.R <govindraj.raja@ti.com>

--
Thanks,
Govindraj.R

[1]:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=659fb32d1b67476f4ade25e9ea0e2642a5b9c4b5;hp=d30e1521b2afb5e6f21ca8bc1a4b6ec2afc93597
--
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] 23+ messages in thread

* Re: [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism
  2011-07-05 10:27 ` [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism Tero Kristo
  2011-07-05 11:18   ` Felipe Balbi
  2011-07-15 13:23   ` Govindraj
@ 2011-07-15 16:40   ` Todd Poynor
  2011-07-18 12:19     ` Tero Kristo
  2011-07-22 22:58   ` Kevin Hilman
  3 siblings, 1 reply; 23+ messages in thread
From: Todd Poynor @ 2011-07-15 16:40 UTC (permalink / raw)
  To: Tero Kristo
  Cc: linux-omap, Thomas Petazzoni, Avinash.H.M, Kevin Hilman, Cousson,
	Benoit, Tony Lindgren, Govindraj.R, Felipe Balbi

On Tue, Jul 05, 2011 at 01:27:47PM +0300, Tero Kristo wrote:
> 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.
> 
...
> +
> +	prcm_wkup_irq = omap_prcm_event_to_irq("wkup");
> +	prcm_io_irq = omap_prcm_event_to_irq("io");


Should check error return for both.

> +
> +	ret = request_irq(prcm_wkup_irq, _prcm_int_handle_wakeup,
> +			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_wkup", NULL);
>  

...
> +	for (i = 0; i <= max_irq / 32; i++) {
> +		gc = irq_alloc_generic_chip("PRCM", 1,
> +			irq_setup->base_irq + i * 32, NULL, handle_level_irq);
> +

Should check NULL return for out of memory.

> +		ct = gc->chip_types;

...
> +	/* Copy setup from __initdata section */
> +	irq_setup = kmalloc(sizeof(struct omap_prcm_irq_setup), GFP_KERNEL);


Check NULL return.

> +	memcpy(irq_setup, setup, sizeof(struct omap_prcm_irq_setup));
> +
> +	irqs = kmalloc(sizeof(struct omap_prcm_irq) *
> +		setup->num_irqs, GFP_KERNEL);

Check NULL return.

> +	memcpy(irqs, setup->irqs, sizeof(struct omap_prcm_irq) *
> +		setup->num_irqs);


Todd

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

* Re: [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism
  2011-07-15 16:40   ` Todd Poynor
@ 2011-07-18 12:19     ` Tero Kristo
  0 siblings, 0 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-18 12:19 UTC (permalink / raw)
  To: Todd Poynor
  Cc: linux-omap, Thomas Petazzoni, Mahadeva, Avinash, Hilman, Kevin,
	Cousson, Benoit, Tony Lindgren, R, Govindraj, Balbi, Felipe

On Fri, 2011-07-15 at 18:40 +0200, Todd Poynor wrote:
> On Tue, Jul 05, 2011 at 01:27:47PM +0300, Tero Kristo wrote:
> > 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.
> > 
> ...
> > +
> > +	prcm_wkup_irq = omap_prcm_event_to_irq("wkup");
> > +	prcm_io_irq = omap_prcm_event_to_irq("io");
> 
> 
> Should check error return for both.

Not needed, the next calls for request_irq will fail if these do not
succeed (attempting to request irq with invalid number.)

Rest of the return value checks I can add to the next version of this
set.

> 
> > +
> > +	ret = request_irq(prcm_wkup_irq, _prcm_int_handle_wakeup,
> > +			IRQF_NO_SUSPEND | IRQF_DISABLED, "prcm_wkup", NULL);
> >  
> 
> ...
> > +	for (i = 0; i <= max_irq / 32; i++) {
> > +		gc = irq_alloc_generic_chip("PRCM", 1,
> > +			irq_setup->base_irq + i * 32, NULL, handle_level_irq);
> > +
> 
> Should check NULL return for out of memory.
> 
> > +		ct = gc->chip_types;
> 
> ...
> > +	/* Copy setup from __initdata section */
> > +	irq_setup = kmalloc(sizeof(struct omap_prcm_irq_setup), GFP_KERNEL);
> 
> 
> Check NULL return.
> 
> > +	memcpy(irq_setup, setup, sizeof(struct omap_prcm_irq_setup));
> > +
> > +	irqs = kmalloc(sizeof(struct omap_prcm_irq) *
> > +		setup->num_irqs, GFP_KERNEL);
> 
> Check NULL return.
> 
> > +	memcpy(irqs, setup->irqs, sizeof(struct omap_prcm_irq) *
> > +		setup->num_irqs);
> 
> 
> Todd



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


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

* Re: [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism
  2011-07-05 10:27 ` [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism Tero Kristo
                     ` (2 preceding siblings ...)
  2011-07-15 16:40   ` Todd Poynor
@ 2011-07-22 22:58   ` Kevin Hilman
  2011-07-22 23:46     ` Felipe Balbi
  3 siblings, 1 reply; 23+ messages in thread
From: Kevin Hilman @ 2011-07-22 22:58 UTC (permalink / raw)
  To: Tero Kristo
  Cc: linux-omap, Thomas Petazzoni, Avinash.H.M, Cousson, Benoit,
	Tony Lindgren, Govindraj.R, Felipe Balbi, Paul Walmsley

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>
> Cc: Felipe Balbi <balbi@ti.com>

Some general comments:

First, we need to get Paul's input on this series as he's the maintainer
of all the PRCM internals.  Please put him on Cc for the next series also.
(I added him on my reply.)

Second, I think you inherited this from the original version, but the
interrupt handling is actually in the PRM, so all of this probably
belongs in the existing PRM files (prm2xxx_3xxx.c, prm4xxx.c.)

Also, for the next merge window, we're likely going to be removing all
of the omap_chip_is* stuff, as it's not scaling well and leading to
messy data sets.

To that end, for the purposes of this series, since we're only currently
using the "wkup" and "io" events, let's just add those and drop all the
chip_is stuff (but leave them defined in the SoC-specific files, since
after we figure out chip_is, we can add the other events.

That will also avoid adding big data arrays which Tony has expressed a
distaste for.

A small handful of minor comments below, but this is looking pretty good
to me.

> ---
>  arch/arm/mach-omap2/Makefile           |    4 +
>  arch/arm/mach-omap2/pm34xx.c           |  108 ++++++++--------------
>  arch/arm/mach-omap2/prcm.c             |  158 ++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/prcm3xxx.c         |  112 ++++++++++++++++++++++
>  arch/arm/mach-omap2/prcm4xxx.c         |  137 +++++++++++++++++++++++++++
>  arch/arm/plat-omap/include/plat/prcm.h |   46 +++++++++
>  6 files changed, 495 insertions(+), 70 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 027958c..8ee70ed 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 3279569..d80bf8b 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;
> +
>  /* pm34xx errata defined in pm.h */
>  u16 pm34xx_errata;
>  
> @@ -235,7 +238,7 @@ 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;
>  
> @@ -247,64 +250,9 @@ static int _prcm_int_handle_wakeup(void)
>  		c += 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;
> +	if (c)
> +		return IRQ_HANDLED;

minor: insert blank line

> +	return IRQ_NONE;
>  }
>  
>  static void omap34xx_do_sram_idle(unsigned long save_state)
> @@ -854,20 +802,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);

As pointed out by Felipe earlier, you can remove IRQF_DISABLED, which is
a nop.

>  
> -	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);

ditto

> +	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);
> @@ -875,7 +838,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");
> @@ -924,14 +887,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..e7d602c 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,162 @@ 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 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()

prcm_irq_handle_virtirqs() doesn't seem to exist.  Comment needs update?

> +	 * 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(irq_setup->base_irq + 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 irq_setup->base_irq + 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);
> +
> +	irq_setup->base_irq = irq_alloc_descs(-1, 0, OMAP_PRCM_NR_IRQS, 0);
> +
> +	if (irq_setup->base_irq < 0) {
> +		pr_err("PRCM: failed to allocate irq descs\n");
> +		irq_set_chained_handler(irq_setup->irq, NULL);
> +		return irq_setup->base_irq;
> +	}
> +
> +	for (i = 0; i <= max_irq / 32; i++) {
> +		gc = irq_alloc_generic_chip("PRCM", 1,
> +			irq_setup->base_irq + i * 32, NULL, handle_level_irq);
> +
> +		ct = gc->chip_types;
> +		ct->chip.irq_ack = irq_gc_ack;
> +		ct->chip.irq_mask = irq_gc_mask_clr_bit;
> +		ct->chip.irq_unmask = irq_gc_mask_set_bit;
> +
> +		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;
> +}
> +
> +/*
> + * 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);
> +
> +	irq_free_descs(irq_setup->base_irq, OMAP_PRCM_NR_IRQS);
> +}
> +
> +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..dea8cca
> --- /dev/null
> +++ b/arch/arm/mach-omap2/prcm3xxx.c
> @@ -0,0 +1,112 @@
> +/*
> + * 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 <plat/io.h>
> +
> +#include "prm-regbits-24xx.h"
> +
> +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 = {
> +	.ack = (u32)OMAP3430_PRM_IRQSTATUS_MPU,
> +	.mask = (u32)OMAP3430_PRM_IRQENABLE_MPU,
> +	.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_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;
> +}

Minor nit: move this function above struct omap_prcm_irq_setup so
forward declaration at beginning of file can be avoided.  Same comment
for OMAP4 below.

> +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..b1f9201
> --- /dev/null
> +++ b/arch/arm/mach-omap2/prcm4xxx.c
> @@ -0,0 +1,137 @@
> +/*
> + * 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 <plat/io.h>
> +
> +#include "prcm44xx.h"
> +#include "prm44xx.h"
> +
> +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 = {
> +	.ack = (u32)OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST,
> +			OMAP4_PRM_IRQSTATUS_MPU_OFFSET),
> +	.mask = (u32)OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST,
> +			OMAP4_PRM_IRQENABLE_MPU_OFFSET),
> +	.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_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/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
> index 267f43b..76acbb7 100644
> --- a/arch/arm/plat-omap/include/plat/prcm.h
> +++ b/arch/arm/plat-omap/include/plat/prcm.h
> @@ -27,6 +27,52 @@
>  #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
> +
> +/* 64 interrupts needed on OMAP4, 32 on OMAP3 */
> +#define OMAP_PRCM_NR_IRQS		64
> +
> +/* Setup for the PRCM interrupt handler */
> +struct omap_prcm_irq_setup {
> +	void (*pending_events)(unsigned long *);
> +	u32 ack;
> +	u32 mask;
> +	struct omap_prcm_irq *irqs;
> +	int num_irqs;
> +	int irq;
> +	int base_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);

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

* Re: [PATCHv5 04/11] OMAP2+: hwmod: add support for PAD wakeup interrupts
  2011-07-05 10:27 ` [PATCHv5 04/11] OMAP2+: hwmod: add support for PAD wakeup interrupts Tero Kristo
@ 2011-07-22 23:04   ` Kevin Hilman
  0 siblings, 0 replies; 23+ messages in thread
From: Kevin Hilman @ 2011-07-22 23:04 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

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

> OMAP hwmod now provides a service routine to parse pending wakeup events
> and to call registered ISR whenever active wakeups are detected. This
> routine is called directly from PRCM interrupt handler.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

Nice!

> ---
>  arch/arm/mach-omap2/omap_hwmod.c             |   19 +++++++++++++++++++
>  arch/arm/mach-omap2/prcm.c                   |    4 ++++
>  arch/arm/plat-omap/include/plat/omap_hwmod.h |    1 +

Minor nit: I think this API belongs in the same place as the other
omap_hwmod_mux_* functions, which are currently in mux.[ch]

Kevin

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

* Re: [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism
  2011-07-22 22:58   ` Kevin Hilman
@ 2011-07-22 23:46     ` Felipe Balbi
  0 siblings, 0 replies; 23+ messages in thread
From: Felipe Balbi @ 2011-07-22 23:46 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Tero Kristo, linux-omap, Thomas Petazzoni, Avinash.H.M, Cousson,
	Benoit, Tony Lindgren, Govindraj.R, Felipe Balbi, Paul Walmsley

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

Hi,

On Fri, Jul 22, 2011 at 03:58:26PM -0700, Kevin Hilman wrote:

[snip]

> > -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;
> > +	if (c)
> > +		return IRQ_HANDLED;
> 
> minor: insert blank line

actually, would be better to just use ternary here ?

	return c ? IRQ_HANDLED : IRQ_NONE;

-- 
balbi

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

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

* Re: [PATCHv5 05/11] TEMP: OMAP3: pm: remove serial resume / idle calls from idle path
  2011-07-05 10:27 ` [PATCHv5 05/11] TEMP: OMAP3: pm: remove serial resume / idle calls from idle path Tero Kristo
@ 2011-07-22 23:51   ` Felipe Balbi
  2011-07-25 16:33     ` Tero Kristo
  0 siblings, 1 reply; 23+ messages in thread
From: Felipe Balbi @ 2011-07-22 23:51 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

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

Hi,

On Tue, Jul 05, 2011 at 01:27:51PM +0300, Tero Kristo wrote:
> This is no longer needed as it will be handled within serial driver itself.
> 
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

isn't this introducing a regression ? Should this, maybe, be merged into
next patch ?

-- 
balbi

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

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

* Re: [PATCHv5 05/11] TEMP: OMAP3: pm: remove serial resume / idle calls from idle path
  2011-07-22 23:51   ` Felipe Balbi
@ 2011-07-25 16:33     ` Tero Kristo
  0 siblings, 0 replies; 23+ messages in thread
From: Tero Kristo @ 2011-07-25 16:33 UTC (permalink / raw)
  To: Balbi, Felipe; +Cc: linux-omap

On Sat, 2011-07-23 at 01:51 +0200, Balbi, Felipe wrote:
> Hi,
> 
> On Tue, Jul 05, 2011 at 01:27:51PM +0300, Tero Kristo wrote:
> > This is no longer needed as it will be handled within serial driver itself.
> > 
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> 
> isn't this introducing a regression ? Should this, maybe, be merged into
> next patch ?
> 

Patches tagged TEMP are not meant for integration, just for testing
purposes.

-Tero



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


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

end of thread, other threads:[~2011-07-25 16:33 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-05 10:27 [PATCHv5 00/11] PRCM chain handler Tero Kristo
2011-07-05 10:27 ` [PATCHv5 01/11] OMAP: prcm: switch to a chained IRQ handler mechanism Tero Kristo
2011-07-05 11:18   ` Felipe Balbi
2011-07-05 11:32     ` Tero Kristo
2011-07-05 11:33       ` Felipe Balbi
2011-07-15 13:23   ` Govindraj
2011-07-15 16:40   ` Todd Poynor
2011-07-18 12:19     ` Tero Kristo
2011-07-22 22:58   ` Kevin Hilman
2011-07-22 23:46     ` Felipe Balbi
2011-07-05 10:27 ` [PATCHv5 02/11] OMAP2+: hwmod: Add API to enable IO ring wakeup Tero Kristo
2011-07-05 10:27 ` [PATCHv5 03/11] OMAP2+: hwmod: Add API to check IO PAD wakeup status Tero Kristo
2011-07-05 10:27 ` [PATCHv5 04/11] OMAP2+: hwmod: add support for PAD wakeup interrupts Tero Kristo
2011-07-22 23:04   ` Kevin Hilman
2011-07-05 10:27 ` [PATCHv5 05/11] TEMP: OMAP3: pm: remove serial resume / idle calls from idle path Tero Kristo
2011-07-22 23:51   ` Felipe Balbi
2011-07-25 16:33     ` Tero Kristo
2011-07-05 10:27 ` [PATCHv5 06/11] TEMP: OMAP3: serial: made serial to work properly with PRCM chain handler Tero Kristo
2011-07-05 10:27 ` [PATCHv5 07/11] TEMP: serial: added mux support Tero Kristo
2011-07-05 10:27 ` [PATCHv5 08/11] TEMP: OMAP device: change pr_warnings to pr_debugs Tero Kristo
2011-07-05 10:27 ` [PATCHv5 09/11] TEMP: OMAP: serial: remove padconf hacks Tero Kristo
2011-07-05 10:27 ` [PATCHv5 10/11] TEMP: OMAP3: pm: disable / enable PRCM chain interrupts during wakeup from suspend Tero Kristo
2011-07-05 10:27 ` [PATCHv5 11/11] OMAP3: pm: do not enable PRCM MPU interrupts manually Tero Kristo

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.