ARM: gic: Move GIC based code out from mpm-8625
Moving code which modifies the GIC registers. As there is no global
lock in gic code, moving the code out.
Change-Id: I85a2bd580dbeefc942a3307f3c0cad8b1da509b7
Signed-off-by: Taniya Das <tdas@codeaurora.org>
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 1107412..875b479 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -1113,3 +1113,113 @@
return 0;
}
#endif
+#ifdef CONFIG_ARCH_MSM8625
+ /*
+ * Check for any interrupts which are enabled are pending
+ * in the pending set or not.
+ * Return :
+ * 0 : No pending interrupts
+ * 1 : Pending interrupts other than A9_M2A_5
+ */
+unsigned int msm_gic_spi_ppi_pending(void)
+{
+ unsigned int i, bit = 0;
+ unsigned int pending_enb = 0, pending = 0;
+ unsigned long value = 0;
+ struct gic_chip_data *gic = &gic_data[0];
+ void __iomem *base = gic_data_dist_base(gic);
+
+ raw_spin_lock(&irq_controller_lock);
+ /*
+ * PPI and SGI to be included.
+ * MSM8625_INT_A9_M2A_5 needs to be ignored, as A9_M2A_5
+ * requesting sleep triggers it
+ */
+ for (i = 0; (i * 32) < gic->max_irq; i++) {
+ pending = readl_relaxed(base +
+ GIC_DIST_PENDING_SET + i * 4);
+ pending_enb = readl_relaxed(base +
+ GIC_DIST_ENABLE_SET + i * 4);
+ value = pending & pending_enb;
+
+ if (value) {
+ for (bit = 0; bit < 32; bit++) {
+ bit = find_next_bit(&value, 32, bit);
+ if ((bit + 32 * i) != MSM8625_INT_A9_M2A_5) {
+ raw_spin_unlock(&irq_controller_lock);
+ return 1;
+ }
+ }
+ }
+ }
+ raw_spin_unlock(&irq_controller_lock);
+
+ return 0;
+}
+
+void msm_gic_save(bool modem_wake, int from_idle)
+{
+ unsigned int i;
+ struct gic_chip_data *gic = &gic_data[0];
+ void __iomem *base = gic_data_dist_base(gic);
+
+ gic_cpu_save(0);
+ gic_dist_save(0);
+ /* Disable all the Interrupts, if we enter from idle pc */
+ if (from_idle) {
+ for (i = 0; (i * 32) < gic->max_irq; i++) {
+ raw_spin_lock(&irq_controller_lock);
+ writel_relaxed(0xffffffff, base
+ + GIC_DIST_ENABLE_CLEAR + i * 4);
+ raw_spin_unlock(&irq_controller_lock);
+ }
+ }
+}
+
+void msm_gic_restore(void)
+{
+ gic_dist_restore(0);
+ gic_cpu_restore(0);
+}
+
+/*
+ * Configure the GIC after we come out of power collapse.
+ * This function will configure some of the GIC registers so as to prepare the
+ * core1 to receive an SPI(ACSR_MP_CORE_IPC1, (32 + 8)), which will bring
+ * core1 out of GDFS.
+ */
+void core1_gic_configure_and_raise(void)
+{
+ struct gic_chip_data *gic = &gic_data[0];
+ void __iomem *base = gic_data_dist_base(gic);
+ unsigned int value = 0;
+
+ raw_spin_lock(&irq_controller_lock);
+
+ value = __raw_readl(base + GIC_DIST_ACTIVE_BIT + 0x4);
+ value |= BIT(8);
+ __raw_writel(value, base + GIC_DIST_ACTIVE_BIT + 0x4);
+ mb();
+
+ value = __raw_readl(base + GIC_DIST_TARGET + 0x24);
+ value |= BIT(13);
+ __raw_writel(value, base + GIC_DIST_TARGET + 0x24);
+ mb();
+
+ value = __raw_readl(base + GIC_DIST_TARGET + 0x28);
+ value |= BIT(1);
+ __raw_writel(value, base + GIC_DIST_TARGET + 0x28);
+ mb();
+
+ value = __raw_readl(base + GIC_DIST_ENABLE_SET + 0x4);
+ value |= BIT(8);
+ __raw_writel(value, base + GIC_DIST_ENABLE_SET + 0x4);
+ mb();
+
+ value = __raw_readl(base + GIC_DIST_PENDING_SET + 0x4);
+ value |= BIT(8);
+ __raw_writel(value, base + GIC_DIST_PENDING_SET + 0x4);
+ mb();
+ raw_spin_unlock(&irq_controller_lock);
+}
+#endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 5668e75..7e1989e 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -63,4 +63,10 @@
#endif
+#ifdef CONFIG_ARCH_MSM8625
+void msm_gic_save(bool modem_wake, int from_idle);
+void msm_gic_restore(void);
+void core1_gic_configure_and_raise(void);
+#endif
+
#endif
diff --git a/arch/arm/mach-msm/mpm-8625.c b/arch/arm/mach-msm/mpm-8625.c
index 6b88103..fa966d2 100644
--- a/arch/arm/mach-msm/mpm-8625.c
+++ b/arch/arm/mach-msm/mpm-8625.c
@@ -25,20 +25,14 @@
#include <asm/hardware/gic.h>
#include <mach/msm_smsm.h>
+#include "mpm-8625.h"
+
#define NUM_REGS_ENABLE 2
/* (NR_MSM_IRQS/32) 96 max irqs supported */
#define NUM_REGS_DISABLE 3
#define GIC_IRQ_MASK(irq) BIT(irq % 32)
#define GIC_IRQ_INDEX(irq) (irq / 32)
-#ifdef CONFIG_PM
-u32 saved_spi_enable[DIV_ROUND_UP(256, 32)];
-u32 saved_spi_conf[DIV_ROUND_UP(256, 16)];
-u32 saved_spi_target[DIV_ROUND_UP(256, 4)];
-u32 __percpu *saved_ppi_enable;
-u32 __percpu *saved_ppi_conf;
-#endif
-
enum {
IRQ_DEBUG_SLEEP_INT_TRIGGER = BIT(0),
IRQ_DEBUG_SLEEP_INT = BIT(1),
@@ -54,10 +48,6 @@
static uint32_t msm_gic_irq_smsm_wake_enable[NUM_REGS_ENABLE];
static uint32_t msm_gic_irq_idle_disable[NUM_REGS_DISABLE];
-static DEFINE_RAW_SPINLOCK(gic_controller_lock);
-static void __iomem *dist_base, *cpu_base;
-static unsigned int max_irqs;
-
/*
* Some of the interrupts which will not be considered as wake capable
* should be marked as FAKE.
@@ -162,158 +152,17 @@
return 0;
}
-#ifdef CONFIG_PM
-static void __init msm_gic_pm_init(void)
-{
- saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
- sizeof(u32));
- BUG_ON(!saved_ppi_enable);
-
- saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
- sizeof(u32));
- BUG_ON(!saved_ppi_conf);
-}
-#endif
-
void __init msm_gic_irq_extn_init(void __iomem *db, void __iomem *cb)
{
- dist_base = db;
- cpu_base = cb;
- max_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x11f;
- max_irqs = (max_irqs + 1) * 32;
-
gic_arch_extn.irq_mask = msm_gic_mask_irq;
gic_arch_extn.irq_unmask = msm_gic_unmask_irq;
gic_arch_extn.irq_disable = msm_gic_mask_irq;
gic_arch_extn.irq_set_wake = msm_gic_set_irq_wake;
-
-#ifdef CONFIG_PM
- msm_gic_pm_init();
-#endif
-}
-
-/* GIC APIs */
-
- /*
- * Save the GIC cpu and distributor context before PC and
- * restor it back after coming out of PC.
- */
-static void msm_gic_save(void)
-{
- int i;
- u32 *ptr;
-
- /* Save the Per CPU PPI's */
- ptr = __this_cpu_ptr(saved_ppi_enable);
- /* 0 - 31 the SGI and PPI */
- ptr[0] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET);
-
- ptr = __this_cpu_ptr(saved_ppi_conf);
- for (i = 0; i < 2; i++)
- ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
-
- /* Save the SPIs */
- for (i = 0; (i * 16) < max_irqs; i++)
- saved_spi_conf[i] =
- readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
-
- for (i = 0; (i * 4) < max_irqs; i++)
- saved_spi_target[i] =
- readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
-
- for (i = 0; (i * 32) < max_irqs; i++)
- saved_spi_enable[i] =
- readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
-}
-
-static void msm_gic_restore(void)
-{
- int i;
- u32 *ptr;
-
- /* restore CPU Interface */
- /* Per CPU SGIs and PPIs */
- ptr = __this_cpu_ptr(saved_ppi_enable);
- writel_relaxed(ptr[0], dist_base + GIC_DIST_ENABLE_SET);
-
- ptr = __this_cpu_ptr(saved_ppi_conf);
- for (i = 0; i < 2; i++)
- writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
-
- for (i = 0; (i * 4) < max_irqs; i++)
- writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
-
- writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
- writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
-
- /* restore Distributor */
- writel_relaxed(0, dist_base + GIC_DIST_CTRL);
-
- for (i = 0; (i * 16) < max_irqs; i++)
- writel_relaxed(saved_spi_conf[i],
- dist_base + GIC_DIST_CONFIG + i * 4);
-
- for (i = 0; (i * 4) < max_irqs; i++)
- writel_relaxed(0xa0a0a0a0,
- dist_base + GIC_DIST_PRI + i * 4);
-
- for (i = 0; (i * 4) < max_irqs; i++)
- writel_relaxed(saved_spi_target[i],
- dist_base + GIC_DIST_TARGET + i * 4);
-
- for (i = 0; (i * 32) < max_irqs; i++)
- writel_relaxed(saved_spi_enable[i],
- dist_base + GIC_DIST_ENABLE_SET + i * 4);
-
- writel_relaxed(1, dist_base + GIC_DIST_CTRL);
-
- mb();
}
/* Power APIs */
/*
- * Check for any interrupts which are enabled are pending
- * in the pending set or not.
- * Return :
- * 0 : No pending interrupts
- * 1 : Pending interrupts other than A9_M2A_5
- */
-unsigned int msm_gic_spi_ppi_pending(void)
-{
- unsigned int i, bit = 0;
- unsigned int pending_enb = 0, pending = 0;
- unsigned long value = 0;
-
- raw_spin_lock(&gic_controller_lock);
- /*
- * PPI and SGI to be included.
- * MSM8625_INT_A9_M2A_5 needs to be ignored, as A9_M2A_5
- * requesting sleep triggers it
- */
- for (i = 0; (i * 32) < max_irqs; i++) {
- pending = readl_relaxed(dist_base +
- GIC_DIST_PENDING_SET + i * 4);
- pending_enb = readl_relaxed(dist_base +
- GIC_DIST_ENABLE_SET + i * 4);
- value = pending & pending_enb;
-
- if (value) {
- for (bit = 0; bit < 32; bit++) {
- bit = find_next_bit(&value, 32, bit);
- if ((bit + 32 * i) != MSM8625_INT_A9_M2A_5) {
- raw_spin_unlock(&gic_controller_lock);
- return 1;
- }
- }
- }
- }
- raw_spin_unlock(&gic_controller_lock);
-
- return 0;
-}
-
- /*
* Iterate over the disable list
*/
@@ -352,8 +201,6 @@
*/
int msm_gic_irq_enter_sleep2(bool modem_wake, int from_idle)
{
- int i;
-
if (from_idle && !modem_wake)
return 0;
@@ -371,14 +218,10 @@
}
if (modem_wake) {
- /* save the contents of GIC CPU interface and Distributor */
- msm_gic_save();
- /* Disable all the Interrupts, if we enter from idle pc */
- if (from_idle) {
- for (i = 0; (i * 32) < max_irqs; i++)
- writel_relaxed(0xffffffff, dist_base
- + GIC_DIST_ENABLE_CLEAR + i * 4);
- }
+ /* save the contents of GIC CPU interface and Distributor
+ * Disable all the Interrupts, if we enter from idle pc
+ */
+ msm_gic_save(modem_wake, from_idle);
irq_set_irq_type(MSM8625_INT_A9_M2A_6, IRQF_TRIGGER_RISING);
enable_irq(MSM8625_INT_A9_M2A_6);
pr_debug("%s going for sleep now\n", __func__);
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
index 23ca454..beab205 100644
--- a/arch/arm/mach-msm/platsmp-8625.c
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -60,7 +60,6 @@
}
static DEFINE_SPINLOCK(boot_lock);
-static DEFINE_RAW_SPINLOCK(irq_controller_lock);
/*
* MP_CORE_IPC will be used to generate interrupt and can be used by either
@@ -79,47 +78,6 @@
mb();
}
-/*
- * Configure the GIC after we come out of power collapse.
- * This function will configure some of the GIC registers so as to prepare the
- * core1 to receive an SPI(ACSR_MP_CORE_IPC1, (32 + 8)), which will bring
- * core1 out of GDFS.
- */
-static void core1_gic_configure_and_raise(void)
-{
- unsigned int value = 0;
-
- raw_spin_lock(&irq_controller_lock);
-
- value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_ACTIVE_BIT + 0x4);
- value |= BIT(8);
- __raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_ACTIVE_BIT + 0x4);
- mb();
-
- value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x24);
- value |= BIT(13);
- __raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x24);
- mb();
-
- value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x28);
- value |= BIT(1);
- __raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x28);
- mb();
-
- value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET + 0x4);
- value |= BIT(8);
- __raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET + 0x4);
- mb();
-
- value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_PENDING_SET + 0x4);
- value |= BIT(8);
- __raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_PENDING_SET + 0x4);
- mb();
-
- raise_clear_spi(1, true);
- raw_spin_unlock(&irq_controller_lock);
-}
-
static void clear_pending_spi(unsigned int irq)
{
/* Clear the IRQ from the ENABLE_SET */
@@ -234,10 +192,12 @@
* needs to be brought out by raising an SPI.
*/
- if (power_collapsed)
+ if (power_collapsed) {
core1_gic_configure_and_raise();
- else
+ raise_clear_spi(1, true);
+ } else {
gic_raise_softirq(cpumask_of(cpu), 1);
+ }
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {