aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/db8500-prcmu.c
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2012-02-28 22:46:06 +0100
committerSamuel Ortiz <sameo@linux.intel.com>2012-03-06 18:46:55 +0100
commitcc9a0f68d1f8b9bfd9c0c2ada13db64d63f63db3 (patch)
tree5adff8293ddbf9ff83b778988b0b22fd22bc1711 /drivers/mfd/db8500-prcmu.c
parentmfd : Cleanup duplicate db8500 definitions (diff)
downloadlinux-dev-cc9a0f68d1f8b9bfd9c0c2ada13db64d63f63db3.tar.xz
linux-dev-cc9a0f68d1f8b9bfd9c0c2ada13db64d63f63db3.zip
mfd : Check if there are pending irq on the db8500 gic
This patch introduces a routine to check if there are some irqs pending on the gic. Usually this check is not relevant because it appears racy (an irq can arrive right after this check), but in the ux500 it makes sense because the prcmu decouples the gic from the A9 cores. Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/db8500-prcmu.c')
-rw-r--r--drivers/mfd/db8500-prcmu.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index d2244dc5d3b1..8346a0e39949 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -30,6 +30,7 @@
#include <linux/mfd/dbx500-prcmu.h>
#include <linux/regulator/db8500-prcmu.h>
#include <linux/regulator/machine.h>
+#include <asm/hardware/gic.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/db8500-regs.h>
@@ -850,6 +851,38 @@ int db8500_prcmu_gic_recouple(void)
return 0;
}
+#define PRCMU_GIC_NUMBER_REGS 5
+
+/*
+ * This function checks if there are pending irq on the gic. It only
+ * makes sense if the gic has been decoupled before with the
+ * db8500_prcmu_gic_decouple function. Disabling an interrupt only
+ * disables the forwarding of the interrupt to any CPU interface. It
+ * does not prevent the interrupt from changing state, for example
+ * becoming pending, or active and pending if it is already
+ * active. Hence, we have to check the interrupt is pending *and* is
+ * active.
+ */
+bool db8500_prcmu_gic_pending_irq(void)
+{
+ u32 pr; /* Pending register */
+ u32 er; /* Enable register */
+ void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE);
+ int i;
+
+ /* 5 registers. STI & PPI not skipped */
+ for (i = 0; i < PRCMU_GIC_NUMBER_REGS; i++) {
+
+ pr = readl_relaxed(dist_base + GIC_DIST_PENDING_SET + i * 4);
+ er = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+ if (pr & er)
+ return true; /* There is a pending interrupt */
+ }
+
+ return false;
+}
+
/* This function should only be called while mb0_transfer.lock is held. */
static void config_wakeups(void)
{