soc: fsl: qe: move qe_ic_cascade_* functions to qe_ic.c
[linux-2.6-microblaze.git] / drivers / soc / fsl / qe / qe_ic.c
index 9bac546..94ccbee 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/spinlock.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <soc/fsl/qe/qe.h>
 #include <soc/fsl/qe/qe_ic.h>
 
 #include "qe_ic.h"
@@ -171,15 +172,15 @@ static struct qe_ic_info qe_ic_info[] = {
                },
 };
 
-static inline u32 qe_ic_read(volatile __be32  __iomem * base, unsigned int reg)
+static inline u32 qe_ic_read(__be32  __iomem *base, unsigned int reg)
 {
-       return in_be32(base + (reg >> 2));
+       return qe_ioread32be(base + (reg >> 2));
 }
 
-static inline void qe_ic_write(volatile __be32  __iomem * base, unsigned int reg,
+static inline void qe_ic_write(__be32  __iomem *base, unsigned int reg,
                               u32 value)
 {
-       out_be32(base + (reg >> 2), value);
+       qe_iowrite32be(value, base + (reg >> 2));
 }
 
 static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
@@ -313,13 +314,55 @@ unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
        return irq_linear_revmap(qe_ic->irqhost, irq);
 }
 
-void __init qe_ic_init(struct device_node *node, unsigned int flags,
-                      void (*low_handler)(struct irq_desc *desc),
-                      void (*high_handler)(struct irq_desc *desc))
+static void qe_ic_cascade_low_mpic(struct irq_desc *desc)
 {
+       struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
+       unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+
+       if (cascade_irq != NO_IRQ)
+               generic_handle_irq(cascade_irq);
+
+       if (chip->irq_eoi)
+               chip->irq_eoi(&desc->irq_data);
+}
+
+static void qe_ic_cascade_high_mpic(struct irq_desc *desc)
+{
+       struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
+       unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+
+       if (cascade_irq != NO_IRQ)
+               generic_handle_irq(cascade_irq);
+
+       if (chip->irq_eoi)
+               chip->irq_eoi(&desc->irq_data);
+}
+
+static void qe_ic_cascade_muxed_mpic(struct irq_desc *desc)
+{
+       struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
+       unsigned int cascade_irq;
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+
+       cascade_irq = qe_ic_get_high_irq(qe_ic);
+       if (cascade_irq == NO_IRQ)
+               cascade_irq = qe_ic_get_low_irq(qe_ic);
+
+       if (cascade_irq != NO_IRQ)
+               generic_handle_irq(cascade_irq);
+
+       chip->irq_eoi(&desc->irq_data);
+}
+
+static void __init qe_ic_init(struct device_node *node, unsigned int flags)
+{
+       void (*low_handler)(struct irq_desc *desc);
+       void (*high_handler)(struct irq_desc *desc);
        struct qe_ic *qe_ic;
        struct resource res;
-       u32 temp = 0, ret, high_active = 0;
+       u32 temp = 0, ret;
 
        ret = of_address_to_resource(node, 0, &res);
        if (ret)
@@ -348,6 +391,13 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags,
                kfree(qe_ic);
                return;
        }
+       if (qe_ic->virq_high != qe_ic->virq_low) {
+               low_handler = qe_ic_cascade_low_mpic;
+               high_handler = qe_ic_cascade_high_mpic;
+       } else {
+               low_handler = qe_ic_cascade_muxed_mpic;
+               high_handler = NULL;
+       }
 
        /* default priority scheme is grouped. If spread mode is    */
        /* required, configure cicr accordingly.                    */
@@ -365,10 +415,8 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags,
                temp |= CICR_GRTB;
 
        /* choose destination signal for highest priority interrupt */
-       if (flags & QE_IC_HIGH_SIGNAL) {
+       if (flags & QE_IC_HIGH_SIGNAL)
                temp |= (SIGNAL_HIGH << CICR_HPIT_SHIFT);
-               high_active = 1;
-       }
 
        qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
 
@@ -382,6 +430,22 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags,
        }
 }
 
+static int __init qe_ic_of_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+       if (!np) {
+               np = of_find_node_by_type(NULL, "qeic");
+               if (!np)
+                       return -ENODEV;
+       }
+       qe_ic_init(np, 0);
+       of_node_put(np);
+       return 0;
+}
+subsys_initcall(qe_ic_of_init);
+
 void qe_ic_set_highest_priority(unsigned int virq, int high)
 {
        struct qe_ic *qe_ic = qe_ic_from_irq(virq);
@@ -475,34 +539,3 @@ int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high)
 
        return 0;
 }
-
-static struct bus_type qe_ic_subsys = {
-       .name = "qe_ic",
-       .dev_name = "qe_ic",
-};
-
-static struct device device_qe_ic = {
-       .id = 0,
-       .bus = &qe_ic_subsys,
-};
-
-static int __init init_qe_ic_sysfs(void)
-{
-       int rc;
-
-       printk(KERN_DEBUG "Registering qe_ic with sysfs...\n");
-
-       rc = subsys_system_register(&qe_ic_subsys, NULL);
-       if (rc) {
-               printk(KERN_ERR "Failed registering qe_ic sys class\n");
-               return -ENODEV;
-       }
-       rc = device_register(&device_qe_ic);
-       if (rc) {
-               printk(KERN_ERR "Failed registering qe_ic sys device\n");
-               return -ENODEV;
-       }
-       return 0;
-}
-
-subsys_initcall(init_qe_ic_sysfs);