]> git.karo-electronics.de Git - linux-beck.git/commitdiff
ARM: EXYNOS4: Add support external GIC
authorChanghwan Youn <chaos.youn@samsung.com>
Sat, 16 Jul 2011 01:49:51 +0000 (10:49 +0900)
committerKukjin Kim <kgene.kim@samsung.com>
Wed, 20 Jul 2011 14:28:28 +0000 (23:28 +0900)
For full support of power modes, this patch adds implementation
external GIC on EXYNOS4.

External GIC of Exynos4 cannot support register banking so
several interrupt related code for CPU1 should be different
from that of CPU0.

Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
arch/arm/mach-exynos4/cpu.c
arch/arm/mach-exynos4/include/mach/entry-macro.S
arch/arm/mach-exynos4/include/mach/map.h
arch/arm/mach-exynos4/platsmp.c

index 1aaad56ca7e7b121bfd3b39b2ea52413f2c09ee4..7dccf4ab11ff29a7f14574937428904eda497c23 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <asm/proc-fns.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>
@@ -160,11 +161,20 @@ void __init exynos4_init_clocks(int xtal)
        exynos4_setup_clocks();
 }
 
+static void exynos4_gic_irq_eoi(struct irq_data *d)
+{
+       struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+       gic_data->cpu_base = S5P_VA_GIC_CPU +
+                           (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+}
+
 void __init exynos4_init_irq(void)
 {
        int irq;
 
        gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+       gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
 
        for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 
index d8f38c2e565408d5ca0e4529d543ca6618453597..4fad076baa434cd94d8ad7195a0143b1ef2eb333 100644 (file)
@@ -10,6 +10,7 @@
 */
 
 #include <mach/hardware.h>
+#include <mach/map.h>
 #include <asm/hardware/gic.h>
 
                .macro  disable_fiq
                .macro  get_irqnr_preamble, base, tmp
                ldr     \base, =gic_cpu_base_addr
                ldr     \base, [\base]
+               mrc     p15, 0, \tmp, c0, c0, 5
+               and     \tmp, \tmp, #3
+               cmp     \tmp, #1
+               addeq   \base, \base, #EXYNOS4_GIC_BANK_OFFSET
                .endm
 
                .macro  arch_ret_to_user, tmp1, tmp2
index 0dbca26dfe6440d7393636aa40e395c2ff7ebae4..36773561f54e8365f2ee63172220117aa919cfab 100644 (file)
@@ -61,6 +61,7 @@
 
 #define EXYNOS4_PA_GIC_CPU             0x10480000
 #define EXYNOS4_PA_GIC_DIST            0x10490000
+#define EXYNOS4_GIC_BANK_OFFSET                0x8000
 
 #define EXYNOS4_PA_COREPERI            0x10500000
 #define EXYNOS4_PA_TWD                 0x10500600
index c5e65a02be8d4e2e4303f1333825e141c5988b66..a79863cb7f7954e7099784ebe5f7e949bf538a06 100644 (file)
@@ -58,6 +58,31 @@ static void __iomem *scu_base_addr(void)
 
 static DEFINE_SPINLOCK(boot_lock);
 
+static void __cpuinit exynos4_gic_secondary_init(void)
+{
+       void __iomem *dist_base = S5P_VA_GIC_DIST +
+                                (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+       void __iomem *cpu_base = S5P_VA_GIC_CPU +
+                               (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+       int i;
+
+       /*
+        * Deal with the banked PPI and SGI interrupts - disable all
+        * PPI interrupts, ensure all SGI interrupts are enabled.
+        */
+       __raw_writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
+       __raw_writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
+
+       /*
+        * Set priority on PPI and SGI interrupts
+        */
+       for (i = 0; i < 32; i += 4)
+               __raw_writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
+
+       __raw_writel(0xf0, cpu_base + GIC_CPU_PRIMASK);
+       __raw_writel(1, cpu_base + GIC_CPU_CTRL);
+}
+
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
        /*
@@ -65,7 +90,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
         * core (e.g. timer irq), then they will not have been enabled
         * for us: do so
         */
-       gic_secondary_init(0);
+       exynos4_gic_secondary_init();
 
        /*
         * let the primary processor know we're out of the