Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0443bbd3 authored by Kevin Corry's avatar Kevin Corry Committed by Paul Mackerras
Browse files

[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: default avatarKevin Corry <kevcorry@us.ibm.com>
Signed-off-by: default avatarCarl Love <carll@us.ibm.com>
Signed-off-by: default avatarArnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent e4f6948c
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -185,6 +185,14 @@ struct cbe_iic_regs {
	struct	cbe_iic_thread_regs thread[2];			/* 0x0400 */
	struct	cbe_iic_thread_regs thread[2];			/* 0x0400 */


	u64	iic_ir;						/* 0x0440 */
	u64	iic_ir;						/* 0x0440 */
#define CBE_IIC_IR_PRIO(x)      (((x) & 0xf) << 12)
#define CBE_IIC_IR_DEST_NODE(x) (((x) & 0xf) << 4)
#define CBE_IIC_IR_DEST_UNIT(x) ((x) & 0xf)
#define CBE_IIC_IR_IOC_0        0x0
#define CBE_IIC_IR_IOC_1S       0xb
#define CBE_IIC_IR_PT_0         0xe
#define CBE_IIC_IR_PT_1         0xf

	u64	iic_is;						/* 0x0448 */
	u64	iic_is;						/* 0x0448 */
#define CBE_IIC_IS_PMI		0x2
#define CBE_IIC_IS_PMI		0x2


+16 −0
Original line number Original line Diff line number Diff line
@@ -396,3 +396,19 @@ void __init iic_init_IRQ(void)
	/* Enable on current CPU */
	/* Enable on current CPU */
	iic_setup_cpu();
	iic_setup_cpu();
}
}

void iic_set_interrupt_routing(int cpu, int thread, int priority)
{
	struct cbe_iic_regs __iomem *iic_regs = cbe_get_cpu_iic_regs(cpu);
	u64 iic_ir = 0;
	int node = cpu >> 1;

	/* Set which node and thread will handle the next interrupt */
	iic_ir |= CBE_IIC_IR_PRIO(priority) |
		  CBE_IIC_IR_DEST_NODE(node);
	if (thread == 0)
		iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_0);
	else
		iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_1);
	out_be64(&iic_regs->iic_ir, iic_ir);
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -83,5 +83,7 @@ extern u8 iic_get_target_id(int cpu);


extern void spider_init_IRQ(void);
extern void spider_init_IRQ(void);


extern void iic_set_interrupt_routing(int cpu, int thread, int priority);

#endif
#endif
#endif /* ASM_CELL_PIC_H */
#endif /* ASM_CELL_PIC_H */
+70 −0
Original line number Original line Diff line number Diff line
@@ -22,9 +22,11 @@
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 */


#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/machdep.h>
#include <asm/pmc.h>
#include <asm/reg.h>
#include <asm/reg.h>
#include <asm/spu.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);
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);
+5 −0
Original line number Original line Diff line number Diff line
@@ -87,4 +87,9 @@ extern void cbe_disable_pm(u32 cpu);


extern void cbe_read_trace_buffer(u32 cpu, u64 *buf);
extern void cbe_read_trace_buffer(u32 cpu, u64 *buf);


extern void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask);
extern void cbe_disable_pm_interrupts(u32 cpu);
extern u32  cbe_query_pm_interrupts(u32 cpu);
extern u32  cbe_clear_pm_interrupts(u32 cpu);

#endif /* __ASM_CELL_PMU_H__ */
#endif /* __ASM_CELL_PMU_H__ */