mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
[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>
This commit is contained in:
parent
e4f6948cfc
commit
0443bbd3d8
@ -185,6 +185,14 @@ struct cbe_iic_regs {
|
||||
struct cbe_iic_thread_regs thread[2]; /* 0x0400 */
|
||||
|
||||
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 */
|
||||
#define CBE_IIC_IS_PMI 0x2
|
||||
|
||||
|
@ -396,3 +396,19 @@ void __init iic_init_IRQ(void)
|
||||
/* Enable on current 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);
|
||||
}
|
||||
|
@ -83,5 +83,7 @@ extern u8 iic_get_target_id(int cpu);
|
||||
|
||||
extern void spider_init_IRQ(void);
|
||||
|
||||
extern void iic_set_interrupt_routing(int cpu, int thread, int priority);
|
||||
|
||||
#endif
|
||||
#endif /* ASM_CELL_PIC_H */
|
||||
|
@ -22,9 +22,11 @@
|
||||
* 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);
|
||||
|
||||
|
@ -87,4 +87,9 @@ extern void cbe_disable_pm(u32 cpu);
|
||||
|
||||
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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user