/*
- * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
- *
* Copyright (C) 1997 Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
* for more details.
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
-#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/sysdev.h>
#include <linux/errno.h>
#include <asm/signal.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/prom.h>
#include <asm/sections.h>
#include <asm/open_pic.h>
#include <asm/i8259.h>
+#include <asm/machdep.h>
#include "open_pic_defs.h"
#define OPENPIC_BIG_ENDIAN
#endif
-void* OpenPIC_Addr;
-static volatile struct OpenPIC *OpenPIC = NULL;
+void __iomem *OpenPIC_Addr;
+static volatile struct OpenPIC __iomem *OpenPIC = NULL;
/*
* We define OpenPIC_InitSenses table thusly:
static u_int NumProcessors;
static u_int NumSources;
static int open_pic_irq_offset;
-static volatile OpenPIC_Source *ISR[NR_IRQS];
+static volatile OpenPIC_Source __iomem *ISR[NR_IRQS];
static int openpic_cascade_irq = -1;
-static int (*openpic_cascade_fn)(struct pt_regs *);
+static int (*openpic_cascade_fn)(void);
/* Global Operations */
static void openpic_disable_8259_pass_through(void);
#ifdef CONFIG_SMP
/* Interprocessor Interrupts */
static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
-static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *);
+static irqreturn_t openpic_ipi_action(int cpl, void *dev_id);
#endif
/* Timer Interrupts */
*/
#ifdef notused
static void openpic_enable_8259_pass_through(void);
-static u_int openpic_get_priority(void);
static u_int openpic_get_spurious(void);
static void openpic_set_sense(u_int irq, int sense);
#endif /* notused */
#define check_arg_cpu(cpu) do {} while (0)
#endif
-u_int openpic_read(volatile u_int *addr)
+u_int openpic_read(volatile u_int __iomem *addr)
{
u_int val;
return val;
}
-static inline void openpic_write(volatile u_int *addr, u_int val)
+static inline void openpic_write(volatile u_int __iomem *addr, u_int val)
{
#ifdef OPENPIC_BIG_ENDIAN
out_be32(addr, val);
#endif
}
-static inline u_int openpic_readfield(volatile u_int *addr, u_int mask)
+static inline u_int openpic_readfield(volatile u_int __iomem *addr, u_int mask)
{
u_int val = openpic_read(addr);
return val & mask;
}
-inline void openpic_writefield(volatile u_int *addr, u_int mask,
+inline void openpic_writefield(volatile u_int __iomem *addr, u_int mask,
u_int field)
{
u_int val = openpic_read(addr);
openpic_write(addr, (val & ~mask) | (field & mask));
}
-static inline void openpic_clearfield(volatile u_int *addr, u_int mask)
+static inline void openpic_clearfield(volatile u_int __iomem *addr, u_int mask)
{
openpic_writefield(addr, mask, 0);
}
-static inline void openpic_setfield(volatile u_int *addr, u_int mask)
+static inline void openpic_setfield(volatile u_int __iomem *addr, u_int mask)
{
openpic_writefield(addr, mask, mask);
}
-static void openpic_safe_writefield(volatile u_int *addr, u_int mask,
+static void openpic_safe_writefield(volatile u_int __iomem *addr, u_int mask,
u_int field)
{
openpic_setfield(addr, OPENPIC_MASK);
#ifdef CONFIG_SMP
/* yes this is right ... bug, feature, you decide! -- tgall */
-u_int openpic_read_IPI(volatile u_int* addr)
+u_int openpic_read_IPI(volatile u_int __iomem * addr)
{
u_int val = 0;
-#if defined(OPENPIC_BIG_ENDIAN) || defined(CONFIG_POWER3)
+#if defined(OPENPIC_BIG_ENDIAN)
val = in_be32(addr);
#else
val = in_le32(addr);
}
/* because of the power3 be / le above, this is needed */
-inline void openpic_writefield_IPI(volatile u_int* addr, u_int mask, u_int field)
+inline void openpic_writefield_IPI(volatile u_int __iomem * addr, u_int mask, u_int field)
{
u_int val = openpic_read_IPI(addr);
openpic_write(addr, (val & ~mask) | (field & mask));
}
-static inline void openpic_clearfield_IPI(volatile u_int *addr, u_int mask)
+static inline void openpic_clearfield_IPI(volatile u_int __iomem *addr, u_int mask)
{
openpic_writefield_IPI(addr, mask, 0);
}
-static inline void openpic_setfield_IPI(volatile u_int *addr, u_int mask)
+static inline void openpic_setfield_IPI(volatile u_int __iomem *addr, u_int mask)
{
openpic_writefield_IPI(addr, mask, mask);
}
-static void openpic_safe_writefield_IPI(volatile u_int *addr, u_int mask, u_int field)
+static void openpic_safe_writefield_IPI(volatile u_int __iomem *addr, u_int mask, u_int field)
{
openpic_setfield_IPI(addr, OPENPIC_MASK);
}
#endif
-#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PM)
+#if defined(CONFIG_EPIC_SERIAL_MODE)
static void openpic_reset(void)
{
openpic_setfield(&OpenPIC->Global.Global_Configuration0,
}
#endif
-void __init openpic_set_sources(int first_irq, int num_irqs, void *first_ISR)
+void __init openpic_set_sources(int first_irq, int num_irqs, void __iomem *first_ISR)
{
- volatile OpenPIC_Source *src = first_ISR;
+ volatile OpenPIC_Source __iomem *src = first_ISR;
int i, last_irq;
last_irq = first_irq + num_irqs;
if (last_irq > NumSources)
NumSources = last_irq;
if (src == 0)
- src = &((struct OpenPIC *)OpenPIC_Addr)->Source[first_irq];
+ src = &((struct OpenPIC __iomem *)OpenPIC_Addr)->Source[first_irq];
for (i = first_irq; i < last_irq; ++i, ++src)
ISR[i] = src;
}
printk("No OpenPIC found !\n");
return;
}
- OpenPIC = (volatile struct OpenPIC *)OpenPIC_Addr;
+ OpenPIC = (volatile struct OpenPIC __iomem *)OpenPIC_Addr;
#ifdef CONFIG_EPIC_SERIAL_MODE
/* Have to start from ground zero.
/* Initialize IPI interrupts */
if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb);
for (i = 0; i < OPENPIC_NUM_IPI; i++) {
- /* Disabled, Priority 10..13 */
- openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset);
+ /* Disabled, increased priorities 10..13 */
+ openpic_initipi(i, OPENPIC_PRIORITY_IPI_BASE+i,
+ OPENPIC_VEC_IPI+i+offset);
/* IPIs are per-CPU */
irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU;
- irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi;
+ irq_desc[OPENPIC_VEC_IPI+i+offset].chip = &open_pic_ipi;
}
#endif
if (sense & IRQ_SENSE_MASK)
irq_desc[i+offset].status = IRQ_LEVEL;
- /* Enabled, Priority 8 */
- openpic_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK),
+ /* Enabled, Default priority */
+ openpic_initirq(i, OPENPIC_PRIORITY_DEFAULT, i+offset,
+ (sense & IRQ_POLARITY_MASK),
(sense & IRQ_SENSE_MASK));
/* Processor 0 */
openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE);
/* Init descriptors */
for (i = offset; i < NumSources + offset; i++)
- irq_desc[i].handler = &open_pic;
+ irq_desc[i].chip = &open_pic;
/* Initialize the spurious interrupt */
if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd);
(void)openpic_read(&OpenPIC->THIS_CPU.EOI);
}
-#ifdef notused
-static u_int openpic_get_priority(void)
+u_int openpic_get_priority(void)
{
DECL_THIS_CPU;
return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
OPENPIC_CURRENT_TASK_PRIORITY_MASK);
}
-#endif /* notused */
void openpic_set_priority(u_int pri)
{
}
#if defined(CONFIG_SMP) || defined(CONFIG_PM)
-static spinlock_t openpic_setup_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(openpic_setup_lock);
#endif
#ifdef CONFIG_SMP
*/
void openpic_cause_IPI(u_int ipi, cpumask_t cpumask)
{
- cpumask_t phys;
DECL_THIS_CPU;
CHECK_THIS_CPU;
check_arg_ipi(ipi);
- phys = physmask(cpumask);
openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
cpus_addr(physmask(cpumask))[0]);
}
if (OpenPIC == NULL)
return;
- /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
+ /*
+ * IPIs are marked IRQF_DISABLED as they must run with irqs
+ * disabled
+ */
request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset,
- openpic_ipi_action, SA_INTERRUPT,
+ openpic_ipi_action, IRQF_DISABLED,
"IPI0 (call function)", NULL);
request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+1,
- openpic_ipi_action, SA_INTERRUPT,
+ openpic_ipi_action, IRQF_DISABLED,
"IPI1 (reschedule)", NULL);
request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+2,
- openpic_ipi_action, SA_INTERRUPT,
+ openpic_ipi_action, IRQF_DISABLED,
"IPI2 (invalidate tlb)", NULL);
request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+3,
- openpic_ipi_action, SA_INTERRUPT,
+ openpic_ipi_action, IRQF_DISABLED,
"IPI3 (xmon break)", NULL);
for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
/* let the openpic know we want intrs. default affinity
* is 0xffffffff until changed via /proc
* That's how it's done on x86. If we want it differently, then
- * we should make sure we also change the default values of irq_affinity
- * in irq.c.
+ * we should make sure we also change the default values of
+ * irq_desc[].affinity in irq.c.
*/
for (i = 0; i < NumSources; i++)
openpic_mapirq(i, msk, CPU_MASK_ALL);
cpus_addr(phys)[0]);
}
+/*
+ * Change the priority of an interrupt
+ */
+void __init
+openpic_set_irq_priority(u_int irq, u_int pri)
+{
+ check_arg_irq(irq);
+ openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
+ OPENPIC_PRIORITY_MASK,
+ pri << OPENPIC_PRIORITY_SHIFT);
+}
+
/*
* Initalize the interrupt source which will generate an NMI.
* This raises the interrupt's priority from 8 to 9.
openpic_init_nmi_irq(u_int irq)
{
check_arg_irq(irq);
- openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
- OPENPIC_PRIORITY_MASK,
- 9 << OPENPIC_PRIORITY_SHIFT);
+ openpic_set_irq_priority(irq, OPENPIC_PRIORITY_NMI);
}
/*
static struct irqaction openpic_cascade_irqaction = {
.handler = no_action,
- .flags = SA_INTERRUPT,
+ .flags = IRQF_DISABLED,
.mask = CPU_MASK_NONE,
};
void __init
openpic_hookup_cascade(u_int irq, char *name,
- int (*cascade_fn)(struct pt_regs *))
+ int (*cascade_fn)(void))
{
openpic_cascade_irq = irq;
openpic_cascade_fn = cascade_fn;
*/
static void openpic_enable_irq(u_int irq)
{
- volatile u_int *vpp;
+ volatile u_int __iomem *vpp;
check_arg_irq(irq);
vpp = &ISR[irq - open_pic_irq_offset]->Vector_Priority;
static void openpic_disable_irq(u_int irq)
{
- volatile u_int *vpp;
+ volatile u_int __iomem *vpp;
u32 vp;
check_arg_irq(irq);
{
}
-static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
+static irqreturn_t openpic_ipi_action(int cpl, void *dev_id)
{
- smp_message_recv(cpl-OPENPIC_VEC_IPI-open_pic_irq_offset, regs);
+ smp_message_recv(cpl-OPENPIC_VEC_IPI-open_pic_irq_offset);
return IRQ_HANDLED;
}
#endif /* CONFIG_SMP */
int
-openpic_get_irq(struct pt_regs *regs)
+openpic_get_irq(void)
{
int irq = openpic_irq();
* This should move to irq.c eventually. -- paulus
*/
if (irq == openpic_cascade_irq && openpic_cascade_fn != NULL) {
- int cirq = openpic_cascade_fn(regs);
+ int cirq = openpic_cascade_fn();
/* Allow for the cascade being shared with other devices */
if (cirq != -1) {
#ifdef CONFIG_SMP
void
-smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
+smp_openpic_message_pass(int target, int msg)
{
cpumask_t mask = CPU_MASK_ALL;
/* make sure we're sending something that translates to an IPI */
* we need something better to deal with that... Maybe switch to S1 for
* cpufreq changes
*/
-int openpic_suspend(struct sys_device *sysdev, u32 state)
+int openpic_suspend(struct sys_device *sysdev, pm_message_t state)
{
int i;
unsigned long flags;
return 0;
}
- openpic_reset();
-
/* OpenPIC sometimes seem to need some time to be fully back up... */
do {
openpic_set_spurious(OPENPIC_VEC_SPURIOUS);