#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/ptrace.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/hardirq.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 *);
/* Global Operations */
static void openpic_disable_8259_pass_through(void);
-static void openpic_set_priority(u_int pri);
static void openpic_set_spurious(u_int vector);
#ifdef CONFIG_SMP
/* Timer Interrupts */
static void openpic_inittimer(u_int timer, u_int pri, u_int vector);
-static void openpic_maptimer(u_int timer, u_int cpumask);
+static void openpic_maptimer(u_int timer, cpumask_t cpumask);
/* Interrupt Sources */
static void openpic_enable_irq(u_int irq);
static void openpic_disable_irq(u_int irq);
static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
int is_level);
-static void openpic_mapirq(u_int irq, u_int cpumask, u_int keepmask);
+static void openpic_mapirq(u_int irq, cpumask_t cpumask, cpumask_t keepmask);
/*
* These functions are not used but the code is kept here
*/
#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 */
*/
static void openpic_end_irq(unsigned int irq_nr);
static void openpic_ack_irq(unsigned int irq_nr);
-static void openpic_set_affinity(unsigned int irq_nr, unsigned long cpumask);
+static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
struct hw_interrupt_type open_pic = {
- " OpenPIC ",
- NULL,
- NULL,
- openpic_enable_irq,
- openpic_disable_irq,
- openpic_ack_irq,
- openpic_end_irq,
- openpic_set_affinity
+ .typename = " OpenPIC ",
+ .enable = openpic_enable_irq,
+ .disable = openpic_disable_irq,
+ .ack = openpic_ack_irq,
+ .end = openpic_end_irq,
+ .set_affinity = openpic_set_affinity,
};
#ifdef CONFIG_SMP
static void openpic_disable_ipi(unsigned int irq_nr);
struct hw_interrupt_type open_pic_ipi = {
- " OpenPIC ",
- NULL,
- NULL,
- openpic_enable_ipi,
- openpic_disable_ipi,
- openpic_ack_ipi,
- openpic_end_ipi,
- 0
+ .typename = " OpenPIC ",
+ .enable = openpic_enable_ipi,
+ .disable = openpic_disable_ipi,
+ .ack = openpic_ack_ipi,
+ .end = openpic_end_ipi,
};
#endif /* CONFIG_SMP */
#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)
}
/* 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 /* CONFIG_SMP */
#ifdef CONFIG_EPIC_SERIAL_MODE
+/* On platforms that may use EPIC serial mode, the default is enabled. */
+int epic_serial_mode = 1;
+
static void __init openpic_eicr_set_clk(u_int clkval)
{
openpic_writefield(&OpenPIC->Global.Global_Configuration1,
}
#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.
/* Disabled, Priority 0 */
openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+offset);
/* No processor */
- openpic_maptimer(i, 0);
+ openpic_maptimer(i, CPU_MASK_NONE);
}
#ifdef CONFIG_SMP
/* 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;
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, 1<<0, 0);
+ openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE);
}
/* Init descriptors */
/* Initialize the spurious interrupt */
if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd);
- openpic_set_spurious(OPENPIC_VEC_SPURIOUS+offset);
+ openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
openpic_disable_8259_pass_through();
#ifdef CONFIG_EPIC_SERIAL_MODE
- openpic_eicr_set_clk(7); /* Slowest value until we know better */
- openpic_enable_sie();
+ if (epic_serial_mode) {
+ openpic_eicr_set_clk(7); /* Slowest value until we know better */
+ openpic_enable_sie();
+ }
#endif
openpic_set_priority(0);
(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 */
-static void __init openpic_set_priority(u_int pri)
+void openpic_set_priority(u_int pri)
{
DECL_THIS_CPU;
/*
* Convert a cpu mask from logical to physical cpu numbers.
*/
-static inline u32 physmask(u32 cpumask)
+static inline cpumask_t physmask(cpumask_t cpumask)
{
int i;
- u32 mask = 0;
+ cpumask_t mask = CPU_MASK_NONE;
+
+ cpus_and(cpumask, cpu_online_map, cpumask);
+
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_isset(i, cpumask))
+ cpu_set(smp_hw_index[i], mask);
- for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
- if (cpu_online(i))
- mask |= (cpumask & 1) << smp_hw_index[i];
return mask;
}
#else
}
#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
* Externally called, however, it takes an IPI number (0...OPENPIC_NUM_IPI)
* and not a system-wide interrupt number
*/
-void openpic_cause_IPI(u_int ipi, u_int cpumask)
+void openpic_cause_IPI(u_int ipi, cpumask_t cpumask)
{
DECL_THIS_CPU;
CHECK_THIS_CPU;
check_arg_ipi(ipi);
openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
- physmask(cpumask));
+ cpus_addr(physmask(cpumask))[0]);
}
void openpic_request_IPIs(void)
/* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset,
openpic_ipi_action, SA_INTERRUPT,
- "IPI0 (call function)", 0);
+ "IPI0 (call function)", NULL);
request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+1,
openpic_ipi_action, SA_INTERRUPT,
- "IPI1 (reschedule)", 0);
+ "IPI1 (reschedule)", NULL);
request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+2,
openpic_ipi_action, SA_INTERRUPT,
- "IPI2 (invalidate tlb)", 0);
+ "IPI2 (invalidate tlb)", NULL);
request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+3,
openpic_ipi_action, SA_INTERRUPT,
- "IPI3 (xmon break)", 0);
+ "IPI3 (xmon break)", NULL);
for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
openpic_enable_ipi(OPENPIC_VEC_IPI+open_pic_irq_offset+i);
{
#ifdef CONFIG_IRQ_ALL_CPUS
int i;
- u32 msk;
+ cpumask_t msk = CPU_MASK_NONE;
#endif
spin_lock(&openpic_setup_lock);
#ifdef CONFIG_IRQ_ALL_CPUS
- msk = 1 << smp_hw_index[smp_processor_id()];
+ cpu_set(smp_hw_index[smp_processor_id()], msk);
/* let the openpic know we want intrs. default affinity
* is 0xffffffff until changed via /proc
* in irq.c.
*/
for (i = 0; i < NumSources; i++)
- openpic_mapirq(i, msk, ~0U);
+ openpic_mapirq(i, msk, CPU_MASK_ALL);
#endif /* CONFIG_IRQ_ALL_CPUS */
openpic_set_priority(0);
/*
* Map a timer interrupt to one or more CPUs
*/
-static void __init openpic_maptimer(u_int timer, u_int cpumask)
+static void __init openpic_maptimer(u_int timer, cpumask_t cpumask)
{
+ cpumask_t phys = physmask(cpumask);
check_arg_timer(timer);
openpic_write(&OpenPIC->Global.Timer[timer].Destination,
- physmask(cpumask));
+ 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);
}
/*
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);
}
/*
/*
* Hookup a cascade to the OpenPIC.
*/
+
+static struct irqaction openpic_cascade_irqaction = {
+ .handler = no_action,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+};
+
void __init
openpic_hookup_cascade(u_int irq, char *name,
int (*cascade_fn)(struct pt_regs *))
{
openpic_cascade_irq = irq;
openpic_cascade_fn = cascade_fn;
- if (request_irq(irq, no_action, SA_INTERRUPT, name, NULL))
+
+ if (setup_irq(irq, &openpic_cascade_irqaction))
printk("Unable to get OpenPIC IRQ %d for cascade\n",
irq - open_pic_irq_offset);
}
*/
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);
/*
* Map an interrupt source to one or more CPUs
*/
-static void openpic_mapirq(u_int irq, u_int physmask, u_int keepmask)
+static void openpic_mapirq(u_int irq, cpumask_t physmask, cpumask_t keepmask)
{
if (ISR[irq] == 0)
return;
- if (keepmask != 0)
- physmask |= openpic_read(&ISR[irq]->Destination) & keepmask;
- openpic_write(&ISR[irq]->Destination, physmask);
+ if (!cpus_empty(keepmask)) {
+ cpumask_t irqdest = { .bits[0] = openpic_read(&ISR[irq]->Destination) };
+ cpus_and(irqdest, irqdest, keepmask);
+ cpus_or(physmask, physmask, irqdest);
+ }
+ openpic_write(&ISR[irq]->Destination, cpus_addr(physmask)[0]);
}
#ifdef notused
#endif
}
-static void openpic_set_affinity(unsigned int irq_nr, unsigned long cpumask)
+static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask)
{
- openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpumask), 0);
+ openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpumask), CPU_MASK_NONE);
}
#ifdef CONFIG_SMP
irq = cirq;
openpic_eoi();
}
- } else if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset)
+ } else if (irq == OPENPIC_VEC_SPURIOUS)
irq = -1;
return irq;
}
#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 */
if (msg > 0x3) {
printk("SMP %d: smp_message_pass: unknown msg %d\n",
}
switch (target) {
case MSG_ALL:
- openpic_cause_IPI(msg, 0xffffffff);
+ openpic_cause_IPI(msg, mask);
break;
case MSG_ALL_BUT_SELF:
- openpic_cause_IPI(msg,
- 0xffffffff & ~(1 << smp_processor_id()));
+ cpu_clear(smp_processor_id(), mask);
+ openpic_cause_IPI(msg, mask);
break;
default:
- openpic_cause_IPI(msg, 1<<target);
+ openpic_cause_IPI(msg, cpumask_of_cpu(target));
break;
}
}
* 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_set_priority(0xf);
+
open_pic.enable = openpic_cached_enable_irq;
open_pic.disable = openpic_cached_disable_irq;
return 0;
}
- openpic_reset();
-
/* OpenPIC sometimes seem to need some time to be fully back up... */
do {
- openpic_set_spurious(OPENPIC_VEC_SPURIOUS+open_pic_irq_offset);
+ openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
} while(openpic_readfield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK)
- != (OPENPIC_VEC_SPURIOUS + open_pic_irq_offset));
+ != OPENPIC_VEC_SPURIOUS);
openpic_disable_8259_pass_through();
open_pic.enable = openpic_enable_irq;
open_pic.disable = openpic_disable_irq;
+ openpic_set_priority(0);
+
spin_unlock_irqrestore(&openpic_setup_lock, flags);
return 0;