OSDN Git Service

Reverting "irqchip: gic: Drop support for gic_arch_extn"
authorMarc Zyngier <marc.zyngier@arm.com>
Wed, 22 Apr 2015 17:20:04 +0000 (18:20 +0100)
committerDavid Keitel <dkeitel@codeaurora.org>
Tue, 22 Mar 2016 18:07:17 +0000 (11:07 -0700)
MSM chipsets rely on arch_extn to get the necessary functionality. Add them
until a upstream solution  can be arrived at.

Change-Id: I773a3e82ca81b1c49cf2581f5288cacaeb6c6db0
Signed-off-by: Mahesh Sivasubramanian <msivasub@codeaurora.org>
drivers/irqchip/irq-gic.c
include/linux/irqchip/arm-gic.h

index abf2ffa..18252fd 100644 (file)
@@ -98,6 +98,18 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
 
 static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE;
+/*
+ * Supported arch specific GIC irq extension.
+ * Default make them NULL.
+ */
+struct irq_chip gic_arch_extn = {
+       .irq_eoi        = NULL,
+       .irq_mask       = NULL,
+       .irq_unmask     = NULL,
+       .irq_retrigger  = NULL,
+       .irq_set_type   = NULL,
+       .irq_set_wake   = NULL,
+};
 
 #ifndef MAX_GIC_NR
 #define MAX_GIC_NR     1
@@ -182,7 +194,13 @@ static int gic_peek_irq(struct irq_data *d, u32 offset)
 
 static void gic_mask_irq(struct irq_data *d)
 {
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&irq_controller_lock, flags);
        gic_poke_irq(d, GIC_DIST_ENABLE_CLEAR);
+       if (gic_arch_extn.irq_mask)
+               gic_arch_extn.irq_mask(d);
+       raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
 }
 
 static void gic_eoimode1_mask_irq(struct irq_data *d)
@@ -202,11 +220,23 @@ static void gic_eoimode1_mask_irq(struct irq_data *d)
 
 static void gic_unmask_irq(struct irq_data *d)
 {
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&irq_controller_lock, flags);
+       if (gic_arch_extn.irq_unmask)
+               gic_arch_extn.irq_unmask(d);
        gic_poke_irq(d, GIC_DIST_ENABLE_SET);
+       raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
 }
 
 static void gic_eoi_irq(struct irq_data *d)
 {
+       if (gic_arch_extn.irq_eoi) {
+               raw_spin_lock(&irq_controller_lock);
+               gic_arch_extn.irq_eoi(d);
+               raw_spin_unlock(&irq_controller_lock);
+       }
+
        writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
 }
 
@@ -272,6 +302,8 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 {
        void __iomem *base = gic_dist_base(d);
        unsigned int gicirq = gic_irq(d);
+       unsigned long flags;
+       int ret;
 
        /* Interrupt configuration for SGIs can't be changed */
        if (gicirq < 16)
@@ -282,7 +314,25 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
                            type != IRQ_TYPE_EDGE_RISING)
                return -EINVAL;
 
-       return gic_configure_irq(gicirq, type, base, NULL);
+       raw_spin_lock_irqsave(&irq_controller_lock, flags);
+
+       if (gic_arch_extn.irq_set_type)
+               gic_arch_extn.irq_set_type(d, type);
+
+       ret = gic_configure_irq(gicirq, type, base, NULL);
+
+       raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
+
+       return ret;
+}
+
+static int gic_retrigger(struct irq_data *d)
+{
+       if (gic_arch_extn.irq_retrigger)
+               return gic_arch_extn.irq_retrigger(d);
+
+       /* the genirq layer expects 0 if we can't retrigger in hardware */
+       return 0;
 }
 
 static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
@@ -326,6 +376,21 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 }
 #endif
 
+#ifdef CONFIG_PM
+static int gic_set_wake(struct irq_data *d, unsigned int on)
+{
+       int ret = -ENXIO;
+
+       if (gic_arch_extn.irq_set_wake)
+               ret = gic_arch_extn.irq_set_wake(d, on);
+
+       return ret;
+}
+
+#else
+#define gic_set_wake   NULL
+#endif
+
 static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 {
        u32 irqstat, irqnr;
@@ -388,9 +453,11 @@ static struct irq_chip gic_chip = {
        .irq_unmask             = gic_unmask_irq,
        .irq_eoi                = gic_eoi_irq,
        .irq_set_type           = gic_set_type,
+       .irq_retrigger          = gic_retrigger,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = gic_set_affinity,
 #endif
+       .irq_set_wake           = gic_set_wake,
        .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
        .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
        .flags                  = IRQCHIP_SET_TYPE_MASKED |
@@ -1139,6 +1206,7 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
                        pr_info("GIC: Using split EOI/Deactivate mode\n");
        }
 
+       gic_chip.flags |= gic_arch_extn.flags;
        gic_dist_init(gic);
        gic_cpu_init(gic);
        gic_pm_init(gic);
index bae69e5..77c08b4 100644 (file)
 
 struct device_node;
 
+extern struct irq_chip gic_arch_extn;
+
+void gic_set_irqchip_flags(unsigned long flags);
+void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
+                   u32 offset, struct device_node *);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 int gic_cpu_if_down(unsigned int gic_nr);