]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/platforms/cell/pmu.c
[POWERPC] cell: Add routines for managing PMU interrupts
[karo-tx-linux.git] / arch / powerpc / platforms / cell / pmu.c
index ae6fd1c12d4e8c750f88dbb0238b73f68cadd88c..f28abf2fc273a7599277c01a82ade0703262ceee 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/interrupt.h>
 #include <linux/types.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
+#include <asm/pmc.h>
 #include <asm/reg.h>
 #include <asm/spu.h>
 
@@ -338,3 +340,71 @@ void cbe_read_trace_buffer(u32 cpu, u64 *buf)
 }
 EXPORT_SYMBOL_GPL(cbe_read_trace_buffer);
 
+/*
+ * Enabling/disabling interrupts for the entire performance monitoring unit.
+ */
+
+u32 cbe_query_pm_interrupts(u32 cpu)
+{
+       return cbe_read_pm(cpu, pm_status);
+}
+EXPORT_SYMBOL_GPL(cbe_query_pm_interrupts);
+
+u32 cbe_clear_pm_interrupts(u32 cpu)
+{
+       /* Reading pm_status clears the interrupt bits. */
+       return cbe_query_pm_interrupts(cpu);
+}
+EXPORT_SYMBOL_GPL(cbe_clear_pm_interrupts);
+
+void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask)
+{
+       /* Set which node and thread will handle the next interrupt. */
+       iic_set_interrupt_routing(cpu, thread, 0);
+
+       /* Enable the interrupt bits in the pm_status register. */
+       if (mask)
+               cbe_write_pm(cpu, pm_status, mask);
+}
+EXPORT_SYMBOL_GPL(cbe_enable_pm_interrupts);
+
+void cbe_disable_pm_interrupts(u32 cpu)
+{
+       cbe_clear_pm_interrupts(cpu);
+       cbe_write_pm(cpu, pm_status, 0);
+}
+EXPORT_SYMBOL_GPL(cbe_disable_pm_interrupts);
+
+static irqreturn_t cbe_pm_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+       perf_irq(regs);
+       return IRQ_HANDLED;
+}
+
+int __init cbe_init_pm_irq(void)
+{
+       unsigned int irq;
+       int rc, node;
+
+       for_each_node(node) {
+               irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI |
+                                              (node << IIC_IRQ_NODE_SHIFT));
+               if (irq == NO_IRQ) {
+                       printk("ERROR: Unable to allocate irq for node %d\n",
+                              node);
+                       return -EINVAL;
+               }
+
+               rc = request_irq(irq, cbe_pm_irq,
+                                IRQF_DISABLED, "cbe-pmu-0", NULL);
+               if (rc) {
+                       printk("ERROR: Request for irq on node %d failed\n",
+                              node);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+arch_initcall(cbe_init_pm_irq);
+