aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2012-02-28 16:46:06 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2012-03-06 12:46:55 -0500
commitcc9a0f68d1f8b9bfd9c0c2ada13db64d63f63db3 (patch)
tree5adff8293ddbf9ff83b778988b0b22fd22bc1711
parent801448e0672008acec050fbef3b8a7df7c5edcc1 (diff)
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>
-rw-r--r--drivers/mfd/db8500-prcmu.c33
-rw-r--r--include/linux/mfd/db8500-prcmu.h1
-rw-r--r--include/linux/mfd/dbx500-prcmu.h8
3 files changed, 42 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 @@
30#include <linux/mfd/dbx500-prcmu.h> 30#include <linux/mfd/dbx500-prcmu.h>
31#include <linux/regulator/db8500-prcmu.h> 31#include <linux/regulator/db8500-prcmu.h>
32#include <linux/regulator/machine.h> 32#include <linux/regulator/machine.h>
33#include <asm/hardware/gic.h>
33#include <mach/hardware.h> 34#include <mach/hardware.h>
34#include <mach/irqs.h> 35#include <mach/irqs.h>
35#include <mach/db8500-regs.h> 36#include <mach/db8500-regs.h>
@@ -850,6 +851,38 @@ int db8500_prcmu_gic_recouple(void)
850 return 0; 851 return 0;
851} 852}
852 853
854#define PRCMU_GIC_NUMBER_REGS 5
855
856/*
857 * This function checks if there are pending irq on the gic. It only
858 * makes sense if the gic has been decoupled before with the
859 * db8500_prcmu_gic_decouple function. Disabling an interrupt only
860 * disables the forwarding of the interrupt to any CPU interface. It
861 * does not prevent the interrupt from changing state, for example
862 * becoming pending, or active and pending if it is already
863 * active. Hence, we have to check the interrupt is pending *and* is
864 * active.
865 */
866bool db8500_prcmu_gic_pending_irq(void)
867{
868 u32 pr; /* Pending register */
869 u32 er; /* Enable register */
870 void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE);
871 int i;
872
873 /* 5 registers. STI & PPI not skipped */
874 for (i = 0; i < PRCMU_GIC_NUMBER_REGS; i++) {
875
876 pr = readl_relaxed(dist_base + GIC_DIST_PENDING_SET + i * 4);
877 er = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
878
879 if (pr & er)
880 return true; /* There is a pending interrupt */
881 }
882
883 return false;
884}
885
853/* This function should only be called while mb0_transfer.lock is held. */ 886/* This function should only be called while mb0_transfer.lock is held. */
854static void config_wakeups(void) 887static void config_wakeups(void)
855{ 888{
diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h
index cf48aa76acc3..92dac13b9ee5 100644
--- a/include/linux/mfd/db8500-prcmu.h
+++ b/include/linux/mfd/db8500-prcmu.h
@@ -582,6 +582,7 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll);
582u8 db8500_prcmu_get_power_state_result(void); 582u8 db8500_prcmu_get_power_state_result(void);
583int db8500_prcmu_gic_decouple(void); 583int db8500_prcmu_gic_decouple(void);
584int db8500_prcmu_gic_recouple(void); 584int db8500_prcmu_gic_recouple(void);
585bool db8500_prcmu_gic_pending_irq(void);
585void db8500_prcmu_enable_wakeups(u32 wakeups); 586void db8500_prcmu_enable_wakeups(u32 wakeups);
586int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state); 587int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state);
587int db8500_prcmu_request_clock(u8 clock, bool enable); 588int db8500_prcmu_request_clock(u8 clock, bool enable);
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index 5bf5c4f0132c..16418747dad1 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -297,6 +297,14 @@ static inline int prcmu_gic_recouple(void)
297 return db8500_prcmu_gic_recouple(); 297 return db8500_prcmu_gic_recouple();
298} 298}
299 299
300static inline bool prcmu_gic_pending_irq(void)
301{
302 if (cpu_is_u5500())
303 return -EINVAL;
304 else
305 return db8500_prcmu_gic_pending_irq();
306}
307
300static inline int prcmu_set_epod(u16 epod_id, u8 epod_state) 308static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
301{ 309{
302 if (cpu_is_u5500()) 310 if (cpu_is_u5500())