]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - sitara-epos/sitara-epos-kernel.git/blobdiff - arch/arm/mach-omap2/prm2xxx_3xxx.c
ARM: OMAP: PRCM: Don't register PRCM chain handler for AM33XX
[sitara-epos/sitara-epos-kernel.git] / arch / arm / mach-omap2 / prm2xxx_3xxx.c
index f02d87f68e5415ddefa5df4b00f0e88d085b4058..fa803c63da8c2185390c3e6a23c4850dfb4915ad 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * OMAP2/3 PRM module functions
  *
- * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010-2011 Texas Instruments, Inc.
  * Copyright (C) 2010 Nokia Corporation
  * BenoĆ®t Cousson
  * Paul Walmsley
@@ -16,7 +16,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 
-#include <plat/common.h>
+#include "common.h"
 #include <plat/cpu.h>
 #include <plat/prcm.h>
 
 #include "prm-regbits-24xx.h"
 #include "prm-regbits-34xx.h"
 
+static const struct omap_prcm_irq omap3_prcm_irqs[] = {
+       OMAP_PRCM_IRQ("wkup",   0,      0),
+       OMAP_PRCM_IRQ("io",     9,      1),
+};
+
+static struct omap_prcm_irq_setup omap3_prcm_irq_setup = {
+       .ack                    = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
+       .mask                   = OMAP3_PRM_IRQENABLE_MPU_OFFSET,
+       .nr_regs                = 1,
+       .irqs                   = omap3_prcm_irqs,
+       .nr_irqs                = ARRAY_SIZE(omap3_prcm_irqs),
+       .irq                    = INT_34XX_PRCM_MPU_IRQ,
+       .read_pending_irqs      = &omap3xxx_prm_read_pending_irqs,
+       .ocp_barrier            = &omap3xxx_prm_ocp_barrier,
+       .save_and_clear_irqen   = &omap3xxx_prm_save_and_clear_irqen,
+       .restore_irqen          = &omap3xxx_prm_restore_irqen,
+};
+
 u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
 {
        return __raw_readl(prm_base + module + idx);
@@ -212,3 +230,80 @@ u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
 {
        return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
 }
+
+/**
+ * omap3xxx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events
+ * @events: ptr to a u32, preallocated by caller
+ *
+ * Read PRM_IRQSTATUS_MPU bits, AND'ed with the currently-enabled PRM
+ * MPU IRQs, and store the result into the u32 pointed to by @events.
+ * No return value.
+ */
+void omap3xxx_prm_read_pending_irqs(unsigned long *events)
+{
+       u32 mask, st;
+
+       /* XXX Can the mask read be avoided (e.g., can it come from RAM?) */
+       mask = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+       st = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+       events[0] = mask & st;
+}
+
+/**
+ * omap3xxx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete
+ *
+ * Force any buffered writes to the PRM IP block to complete.  Needed
+ * by the PRM IRQ handler, which reads and writes directly to the IP
+ * block, to avoid race conditions after acknowledging or clearing IRQ
+ * bits.  No return value.
+ */
+void omap3xxx_prm_ocp_barrier(void)
+{
+       omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
+}
+
+/**
+ * omap3xxx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU reg
+ * @saved_mask: ptr to a u32 array to save IRQENABLE bits
+ *
+ * Save the PRM_IRQENABLE_MPU register to @saved_mask.  @saved_mask
+ * must be allocated by the caller.  Intended to be used in the PRM
+ * interrupt handler suspend callback.  The OCP barrier is needed to
+ * ensure the write to disable PRM interrupts reaches the PRM before
+ * returning; otherwise, spurious interrupts might occur.  No return
+ * value.
+ */
+void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask)
+{
+       saved_mask[0] = omap2_prm_read_mod_reg(OCP_MOD,
+                                              OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+       omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+
+       /* OCP barrier */
+       omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
+}
+
+/**
+ * omap3xxx_prm_restore_irqen - set PRM_IRQENABLE_MPU register from args
+ * @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously
+ *
+ * Restore the PRM_IRQENABLE_MPU register from @saved_mask.  Intended
+ * to be used in the PRM interrupt handler resume callback to restore
+ * values saved by omap3xxx_prm_save_and_clear_irqen().  No OCP
+ * barrier should be needed here; any pending PRM interrupts will fire
+ * once the writes reach the PRM.  No return value.
+ */
+void omap3xxx_prm_restore_irqen(u32 *saved_mask)
+{
+       omap2_prm_write_mod_reg(saved_mask[0], OCP_MOD,
+                               OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+}
+
+static int __init omap3xxx_prcm_init(void)
+{
+       if (cpu_is_omap34xx() && !cpu_is_am33xx())
+               return omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
+       return 0;
+}
+subsys_initcall(omap3xxx_prcm_init);