aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorKevin Corry <kevcorry@us.ibm.com>2006-11-20 12:45:15 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:40:12 -0500
commit0443bbd3d8496f9c2bc3e8c9d1833c6638722743 (patch)
tree7166aeb19de3d4cc538c7153843e009a5a33f32b /arch/powerpc
parente4f6948cfc8b9626022db0f93e7cf2ce5c0998cd (diff)
[POWERPC] cell: Add routines for managing PMU interrupts
The following routines are added to arch/powerpc/platforms/cell/pmu.c: cbe_clear_pm_interrupts() cbe_enable_pm_interrupts() cbe_disable_pm_interrupts() cbe_query_pm_interrupts() cbe_pm_irq() cbe_init_pm_irq() This also adds a routine in arch/powerpc/platforms/cell/interrupt.c and some macros in cbe_regs.h to manipulate the IIC_IR register: iic_set_interrupt_routing() Signed-off-by: Kevin Corry <kevcorry@us.ibm.com> Signed-off-by: Carl Love <carll@us.ibm.com> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.h8
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c16
-rw-r--r--arch/powerpc/platforms/cell/interrupt.h2
-rw-r--r--arch/powerpc/platforms/cell/pmu.c70
4 files changed, 96 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h
index a29f4a5f52c5..440a7ecc66ea 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.h
+++ b/arch/powerpc/platforms/cell/cbe_regs.h
@@ -185,6 +185,14 @@ struct cbe_iic_regs {
185 struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ 185 struct cbe_iic_thread_regs thread[2]; /* 0x0400 */
186 186
187 u64 iic_ir; /* 0x0440 */ 187 u64 iic_ir; /* 0x0440 */
188#define CBE_IIC_IR_PRIO(x) (((x) & 0xf) << 12)
189#define CBE_IIC_IR_DEST_NODE(x) (((x) & 0xf) << 4)
190#define CBE_IIC_IR_DEST_UNIT(x) ((x) & 0xf)
191#define CBE_IIC_IR_IOC_0 0x0
192#define CBE_IIC_IR_IOC_1S 0xb
193#define CBE_IIC_IR_PT_0 0xe
194#define CBE_IIC_IR_PT_1 0xf
195
188 u64 iic_is; /* 0x0448 */ 196 u64 iic_is; /* 0x0448 */
189#define CBE_IIC_IS_PMI 0x2 197#define CBE_IIC_IS_PMI 0x2
190 198
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index a914c12b4060..6666d037eb44 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -396,3 +396,19 @@ void __init iic_init_IRQ(void)
396 /* Enable on current CPU */ 396 /* Enable on current CPU */
397 iic_setup_cpu(); 397 iic_setup_cpu();
398} 398}
399
400void iic_set_interrupt_routing(int cpu, int thread, int priority)
401{
402 struct cbe_iic_regs __iomem *iic_regs = cbe_get_cpu_iic_regs(cpu);
403 u64 iic_ir = 0;
404 int node = cpu >> 1;
405
406 /* Set which node and thread will handle the next interrupt */
407 iic_ir |= CBE_IIC_IR_PRIO(priority) |
408 CBE_IIC_IR_DEST_NODE(node);
409 if (thread == 0)
410 iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_0);
411 else
412 iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_1);
413 out_be64(&iic_regs->iic_ir, iic_ir);
414}
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
index 9ba1d3c17b4b..942dc39d6045 100644
--- a/arch/powerpc/platforms/cell/interrupt.h
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -83,5 +83,7 @@ extern u8 iic_get_target_id(int cpu);
83 83
84extern void spider_init_IRQ(void); 84extern void spider_init_IRQ(void);
85 85
86extern void iic_set_interrupt_routing(int cpu, int thread, int priority);
87
86#endif 88#endif
87#endif /* ASM_CELL_PIC_H */ 89#endif /* ASM_CELL_PIC_H */
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
index ae6fd1c12d4e..f28abf2fc273 100644
--- a/arch/powerpc/platforms/cell/pmu.c
+++ b/arch/powerpc/platforms/cell/pmu.c
@@ -22,9 +22,11 @@
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */ 23 */
24 24
25#include <linux/interrupt.h>
25#include <linux/types.h> 26#include <linux/types.h>
26#include <asm/io.h> 27#include <asm/io.h>
27#include <asm/machdep.h> 28#include <asm/machdep.h>
29#include <asm/pmc.h>
28#include <asm/reg.h> 30#include <asm/reg.h>
29#include <asm/spu.h> 31#include <asm/spu.h>
30 32
@@ -338,3 +340,71 @@ void cbe_read_trace_buffer(u32 cpu, u64 *buf)
338} 340}
339EXPORT_SYMBOL_GPL(cbe_read_trace_buffer); 341EXPORT_SYMBOL_GPL(cbe_read_trace_buffer);
340 342
343/*
344 * Enabling/disabling interrupts for the entire performance monitoring unit.
345 */
346
347u32 cbe_query_pm_interrupts(u32 cpu)
348{
349 return cbe_read_pm(cpu, pm_status);
350}
351EXPORT_SYMBOL_GPL(cbe_query_pm_interrupts);
352
353u32 cbe_clear_pm_interrupts(u32 cpu)
354{
355 /* Reading pm_status clears the interrupt bits. */
356 return cbe_query_pm_interrupts(cpu);
357}
358EXPORT_SYMBOL_GPL(cbe_clear_pm_interrupts);
359
360void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask)
361{
362 /* Set which node and thread will handle the next interrupt. */
363 iic_set_interrupt_routing(cpu, thread, 0);
364
365 /* Enable the interrupt bits in the pm_status register. */
366 if (mask)
367 cbe_write_pm(cpu, pm_status, mask);
368}
369EXPORT_SYMBOL_GPL(cbe_enable_pm_interrupts);
370
371void cbe_disable_pm_interrupts(u32 cpu)
372{
373 cbe_clear_pm_interrupts(cpu);
374 cbe_write_pm(cpu, pm_status, 0);
375}
376EXPORT_SYMBOL_GPL(cbe_disable_pm_interrupts);
377
378static irqreturn_t cbe_pm_irq(int irq, void *dev_id, struct pt_regs *regs)
379{
380 perf_irq(regs);
381 return IRQ_HANDLED;
382}
383
384int __init cbe_init_pm_irq(void)
385{
386 unsigned int irq;
387 int rc, node;
388
389 for_each_node(node) {
390 irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI |
391 (node << IIC_IRQ_NODE_SHIFT));
392 if (irq == NO_IRQ) {
393 printk("ERROR: Unable to allocate irq for node %d\n",
394 node);
395 return -EINVAL;
396 }
397
398 rc = request_irq(irq, cbe_pm_irq,
399 IRQF_DISABLED, "cbe-pmu-0", NULL);
400 if (rc) {
401 printk("ERROR: Request for irq on node %d failed\n",
402 node);
403 return rc;
404 }
405 }
406
407 return 0;
408}
409arch_initcall(cbe_init_pm_irq);
410