ARC: move mcip.h into include/soc and adjust the includes
[linux-2.6-block.git] / arch / arc / kernel / mcip.c
index c424d5abc318a220f07d4724b8796a35280f4e7e..560c4afc2af4882f7e64191350be90efef808754 100644 (file)
@@ -11,8 +11,8 @@
 #include <linux/smp.h>
 #include <linux/irq.h>
 #include <linux/spinlock.h>
+#include <soc/arc/mcip.h>
 #include <asm/irqflags-arcv2.h>
-#include <asm/mcip.h>
 #include <asm/setup.h>
 
 static DEFINE_RAW_SPINLOCK(mcip_lock);
@@ -181,6 +181,8 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
 {
        unsigned long flags;
        cpumask_t online;
+       unsigned int destination_bits;
+       unsigned int distribution_mode;
 
        /* errout if no online cpu per @cpumask */
        if (!cpumask_and(&online, cpumask, cpu_online_mask))
@@ -188,8 +190,15 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
 
        raw_spin_lock_irqsave(&mcip_lock, flags);
 
-       idu_set_dest(data->hwirq, cpumask_bits(&online)[0]);
-       idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
+       destination_bits = cpumask_bits(&online)[0];
+       idu_set_dest(data->hwirq, destination_bits);
+
+       if (ffs(destination_bits) == fls(destination_bits))
+               distribution_mode = IDU_M_DISTRI_DEST;
+       else
+               distribution_mode = IDU_M_DISTRI_RR;
+
+       idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, distribution_mode);
 
        raw_spin_unlock_irqrestore(&mcip_lock, flags);
 
@@ -207,16 +216,15 @@ static struct irq_chip idu_irq_chip = {
 
 };
 
-static int idu_first_irq;
+static irq_hw_number_t idu_first_hwirq;
 
 static void idu_cascade_isr(struct irq_desc *desc)
 {
-       struct irq_domain *domain = irq_desc_get_handler_data(desc);
-       unsigned int core_irq = irq_desc_get_irq(desc);
-       unsigned int idu_irq;
+       struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
+       irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
+       irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
 
-       idu_irq = core_irq - idu_first_irq;
-       generic_handle_irq(irq_find_mapping(domain, idu_irq));
+       generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
 }
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq)
@@ -282,7 +290,7 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
        struct irq_domain *domain;
        /* Read IDU BCR to confirm nr_irqs */
        int nr_irqs = of_irq_count(intc);
-       int i, irq;
+       int i, virq;
        struct mcip_bcr mp;
 
        READ_BCR(ARC_REG_MCIP_BCR, mp);
@@ -303,11 +311,11 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
                 * however we need it to get the parent virq and set IDU handler
                 * as first level isr
                 */
-               irq = irq_of_parse_and_map(intc, i);
+               virq = irq_of_parse_and_map(intc, i);
                if (!i)
-                       idu_first_irq = irq;
+                       idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));
 
-               irq_set_chained_handler_and_data(irq, idu_cascade_isr, domain);
+               irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
        }
 
        __mcip_cmd(CMD_IDU_ENABLE, 0);