Commit 378193eb authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Linus Torvalds

[PATCH] ppc64: Rewrite the openpic driver

This patch replaces the open_pic IRQ controller driver with a new
version rewritten from scratch, called "mpic" (this is the name of
IBM's open_pic implementation and also the only one actually used
on any platform).

It is smaller, hopefully more readable, supports the various variants
of the cell in a single driver (open_pic_u3.c is gone), and adds
optional support for the workaround of U3 mpic beeing used along with
IO-APICs on HyperTransport (the eval board will uses that, among
others).
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 97c0b6a4
......@@ -28,7 +28,7 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
iSeries_iommu.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o open_pic.o i8259.o prom_init.o prom.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o mpic.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
eeh.o pSeries_nvram.o rtasd.o ras.o \
......@@ -47,8 +47,8 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_HVCS) += hvcserver.o
obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \
pmac_time.o pmac_nvram.o pmac_low_i2c.o \
open_pic_u3.o
pmac_time.o pmac_nvram.o pmac_low_i2c.o
obj-$(CONFIG_U3_DART) += u3_iommu.o
ifdef CONFIG_SMP
......
......@@ -23,7 +23,8 @@ unsigned char cached_8259[2] = { 0xff, 0xff };
static spinlock_t i8259_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
int i8259_pic_irq_offset;
static int i8259_pic_irq_offset;
static int i8259_present;
int i8259_irq(int cpu)
{
......@@ -140,11 +141,13 @@ struct hw_interrupt_type i8259_pic = {
NULL
};
void __init i8259_init(void)
void __init i8259_init(int offset)
{
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
i8259_pic_irq_offset = offset;
i8259_present = 1;
/* init master interrupt controller */
outb(0x11, 0x20); /* Start init sequence */
outb(0x00, 0x21); /* Vector base */
......@@ -160,7 +163,18 @@ void __init i8259_init(void)
outb(cached_A1, 0xA1);
outb(cached_21, 0x21);
spin_unlock_irqrestore(&i8259_lock, flags);
}
static int i8259_request_cascade(void)
{
if (!i8259_present)
return -ENODEV;
request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
"82c59 secondary cascade", NULL );
return 0;
}
arch_initcall(i8259_request_cascade);
......@@ -11,7 +11,7 @@
extern struct hw_interrupt_type i8259_pic;
void i8259_init(void);
int i8259_irq(int);
extern void i8259_init(int offset);
extern int i8259_irq(int);
#endif /* _PPC_KERNEL_i8259_H */
This diff is collapsed.
#include <linux/irq.h>
/*
* Global registers
*/
#define MPIC_GREG_BASE 0x01000
#define MPIC_GREG_FEATURE_0 0x00000
#define MPIC_GREG_FEATURE_LAST_SRC_MASK 0x07ff0000
#define MPIC_GREG_FEATURE_LAST_SRC_SHIFT 16
#define MPIC_GREG_FEATURE_LAST_CPU_MASK 0x00001f00
#define MPIC_GREG_FEATURE_LAST_CPU_SHIFT 8
#define MPIC_GREG_FEATURE_VERSION_MASK 0xff
#define MPIC_GREG_FEATURE_1 0x00010
#define MPIC_GREG_GLOBAL_CONF_0 0x00020
#define MPIC_GREG_GCONF_RESET 0x80000000
#define MPIC_GREG_GCONF_8259_PTHROU_DIS 0x20000000
#define MPIC_GREG_GCONF_BASE_MASK 0x000fffff
#define MPIC_GREG_GLOBAL_CONF_1 0x00030
#define MPIC_GREG_VENDOR_0 0x00040
#define MPIC_GREG_VENDOR_1 0x00050
#define MPIC_GREG_VENDOR_2 0x00060
#define MPIC_GREG_VENDOR_3 0x00070
#define MPIC_GREG_VENDOR_ID 0x00080
#define MPIC_GREG_VENDOR_ID_STEPPING_MASK 0x00ff0000
#define MPIC_GREG_VENDOR_ID_STEPPING_SHIFT 16
#define MPIC_GREG_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00
#define MPIC_GREG_VENDOR_ID_DEVICE_ID_SHIFT 8
#define MPIC_GREG_VENDOR_ID_VENDOR_ID_MASK 0x000000ff
#define MPIC_GREG_PROCESSOR_INIT 0x00090
#define MPIC_GREG_IPI_VECTOR_PRI_0 0x000a0
#define MPIC_GREG_IPI_VECTOR_PRI_1 0x000b0
#define MPIC_GREG_IPI_VECTOR_PRI_2 0x000c0
#define MPIC_GREG_IPI_VECTOR_PRI_3 0x000d0
#define MPIC_GREG_SPURIOUS 0x000e0
#define MPIC_GREG_TIMER_FREQ 0x000f0
/*
*
* Timer registers
*/
#define MPIC_TIMER_BASE 0x01100
#define MPIC_TIMER_STRIDE 0x40
#define MPIC_TIMER_CURRENT_CNT 0x00000
#define MPIC_TIMER_BASE_CNT 0x00010
#define MPIC_TIMER_VECTOR_PRI 0x00020
#define MPIC_TIMER_DESTINATION 0x00030
/*
* Per-Processor registers
*/
#define MPIC_CPU_THISBASE 0x00000
#define MPIC_CPU_BASE 0x20000
#define MPIC_CPU_STRIDE 0x01000
#define MPIC_CPU_IPI_DISPATCH_0 0x00040
#define MPIC_CPU_IPI_DISPATCH_1 0x00050
#define MPIC_CPU_IPI_DISPATCH_2 0x00060
#define MPIC_CPU_IPI_DISPATCH_3 0x00070
#define MPIC_CPU_CURRENT_TASK_PRI 0x00080
#define MPIC_CPU_TASKPRI_MASK 0x0000000f
#define MPIC_CPU_WHOAMI 0x00090
#define MPIC_CPU_WHOAMI_MASK 0x0000001f
#define MPIC_CPU_INTACK 0x000a0
#define MPIC_CPU_EOI 0x000b0
/*
* Per-source registers
*/
#define MPIC_IRQ_BASE 0x10000
#define MPIC_IRQ_STRIDE 0x00020
#define MPIC_IRQ_VECTOR_PRI 0x00000
#define MPIC_VECPRI_MASK 0x80000000
#define MPIC_VECPRI_ACTIVITY 0x40000000 /* Read Only */
#define MPIC_VECPRI_PRIORITY_MASK 0x000f0000
#define MPIC_VECPRI_PRIORITY_SHIFT 16
#define MPIC_VECPRI_VECTOR_MASK 0x000007ff
#define MPIC_VECPRI_POLARITY_POSITIVE 0x00800000
#define MPIC_VECPRI_POLARITY_NEGATIVE 0x00000000
#define MPIC_VECPRI_POLARITY_MASK 0x00800000
#define MPIC_VECPRI_SENSE_LEVEL 0x00400000
#define MPIC_VECPRI_SENSE_EDGE 0x00000000
#define MPIC_VECPRI_SENSE_MASK 0x00400000
#define MPIC_IRQ_DESTINATION 0x00010
#define MPIC_MAX_IRQ_SOURCES 2048
#define MPIC_MAX_CPUS 32
#define MPIC_MAX_ISU 32
/*
* Special vector numbers (internal use only)
*/
#define MPIC_VEC_SPURRIOUS 255
#define MPIC_VEC_IPI_3 254
#define MPIC_VEC_IPI_2 253
#define MPIC_VEC_IPI_1 252
#define MPIC_VEC_IPI_0 251
/* unused */
#define MPIC_VEC_TIMER_3 250
#define MPIC_VEC_TIMER_2 249
#define MPIC_VEC_TIMER_1 248
#define MPIC_VEC_TIMER_0 247
/* Type definition of the cascade handler */
typedef int (*mpic_cascade_t)(struct pt_regs *regs, void *data);
#ifdef CONFIG_MPIC_BROKEN_U3
/* Fixup table entry */
struct mpic_irq_fixup
{
u8 __iomem *base;
unsigned int irq;
};
#endif /* CONFIG_MPIC_BROKEN_U3 */
/* The instance data of a given MPIC */
struct mpic
{
/* The "linux" controller struct */
hw_irq_controller hc_irq;
#ifdef CONFIG_SMP
hw_irq_controller hc_ipi;
#endif
const char *name;
/* Flags */
unsigned int flags;
/* How many irq sources in a given ISU */
unsigned int isu_size;
unsigned int isu_shift;
unsigned int isu_mask;
/* Offset of irq vector numbers */
unsigned int irq_offset;
unsigned int irq_count;
/* Offset of ipi vector numbers */
unsigned int ipi_offset;
/* Number of sources */
unsigned int num_sources;
/* Number of CPUs */
unsigned int num_cpus;
/* cascade handler */
mpic_cascade_t cascade;
void *cascade_data;
unsigned int cascade_vec;
/* senses array */
unsigned char *senses;
unsigned int senses_count;
#ifdef CONFIG_MPIC_BROKEN_U3
/* The fixup table */
struct mpic_irq_fixup *fixups;
spinlock_t fixup_lock;
#endif
/* The various ioremap'ed bases */
volatile u32 __iomem *gregs;
volatile u32 __iomem *tmregs;
volatile u32 __iomem *cpuregs[MPIC_MAX_CPUS];
volatile u32 __iomem *isus[MPIC_MAX_ISU];
/* link */
struct mpic *next;
};
/* This is the primary controller, only that one has IPIs and
* has afinity control. A non-primary MPIC always uses CPU0
* registers only
*/
#define MPIC_PRIMARY 0x00000001
/* Set this for a big-endian MPIC */
#define MPIC_BIG_ENDIAN 0x00000002
/* Broken U3 MPIC */
#define MPIC_BROKEN_U3 0x00000004
/* Broken IPI registers (autodetected) */
#define MPIC_BROKEN_IPI 0x00000008
/* MPIC wants a reset */
#define MPIC_WANTS_RESET 0x00000010
/* Allocate the controller structure and setup the linux irq descs
* for the range if interrupts passed in. No HW initialization is
* actually performed.
*
* @phys_addr: physial base address of the MPIC
* @flags: flags, see constants above
* @isu_size: number of interrupts in an ISU. Use 0 to use a
* standard ISU-less setup (aka powermac)
* @irq_offset: first irq number to assign to this mpic
* @irq_count: number of irqs to use with this mpic IRQ sources. Pass 0
* to match the number of sources
* @ipi_offset: first irq number to assign to this mpic IPI sources,
* used only on primary mpic
* @senses: array of sense values
* @senses_num: number of entries in the array
*
* Note about the sense array. If none is passed, all interrupts are
* setup to be level negative unless MPIC_BROKEN_U3 is set in which
* case they are edge positive (and the array is ignored anyway).
* The values in the array start at the first source of the MPIC,
* that is senses[0] correspond to linux irq "irq_offset".
*/
extern struct mpic *mpic_alloc(unsigned long phys_addr,
unsigned int flags,
unsigned int isu_size,
unsigned int irq_offset,
unsigned int irq_count,
unsigned int ipi_offset,
unsigned char *senses,
unsigned int senses_num,
const char *name);
/* Assign ISUs, to call before mpic_init()
*
* @mpic: controller structure as returned by mpic_alloc()
* @isu_num: ISU number
* @phys_addr: physical address of the ISU
*/
extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
unsigned long phys_addr);
/* Initialize the controller. After this has been called, none of the above
* should be called again for this mpic
*/
extern void mpic_init(struct mpic *mpic);
/* Setup a cascade. Currently, only one cascade is supported this
* way, though you can always do a normal request_irq() and add
* other cascades this way. You should call this _after_ having
* added all the ISUs
*
* @irq_no: "linux" irq number of the cascade (that is offset'ed vector)
* @handler: cascade handler function
*/
extern void mpic_setup_cascade(unsigned int irq_no, mpic_cascade_t hanlder,
void *data);
/*
* All of the following functions must only be used after the
* ISUs have been assigned and the controller fully initialized
* with mpic_init()
*/
/* Change/Read the priority of an interrupt. Default is 8 for irqs and
* 10 for IPIs. You can call this on both IPIs and IRQ numbers, but the
* IPI number is then the offset'ed (linux irq number mapped to the IPI)
*/
extern void mpic_irq_set_priority(unsigned int irq, unsigned int pri);
extern unsigned int mpic_irq_get_priority(unsigned int irq);
/* Setup a non-boot CPU */
extern void mpic_setup_this_cpu(void);
/* Request IPIs on primary mpic */
extern void mpic_request_ipis(void);
/* Send an IPI (non offseted number 0..3) */
extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask);
/* Fetch interrupt from a given mpic */
extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);
/* This one gets to the primary mpic */
extern int mpic_get_irq(struct pt_regs *regs);
This diff is collapsed.
/*
* arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling
*
* Copyright (C) 1997 Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*
*/
#ifndef _PPC64_KERNEL_OPEN_PIC_H
#define _PPC64_KERNEL_OPEN_PIC_H
#include <linux/config.h>
#include <linux/cpumask.h>
#include <linux/irq.h>
#define OPENPIC_SIZE 0x40000
/* OpenPIC IRQ controller structure */
extern struct hw_interrupt_type open_pic;
/* OpenPIC IPI controller structure */
#ifdef CONFIG_SMP
extern struct hw_interrupt_type open_pic_ipi;
#endif /* CONFIG_SMP */
extern u_int OpenPIC_NumInitSenses;
extern u_char *OpenPIC_InitSenses;
extern void* OpenPIC_Addr;
/* Exported functions */
extern void openpic_init(int, int, unsigned char *, int);
extern void openpic_request_IPIs(void);
extern void do_openpic_setup_cpu(void);
extern int openpic_get_irq(struct pt_regs *regs);
extern void openpic_init_processor(u_int cpumask);
extern void openpic_setup_ISU(int isu_num, unsigned long addr);
extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
#endif /* _PPC64_KERNEL_OPEN_PIC_H */
/*
* linux/openpic.h -- OpenPIC definitions
*
* Copyright (C) 1997 Geert Uytterhoeven
*
* This file is based on the following documentation:
*
* The Open Programmable Interrupt Controller (PIC)
* Register Interface Specification Revision 1.2
*
* Issue Date: October 1995
*
* Issued jointly by Advanced Micro Devices and Cyrix Corporation
*
* AMD is a registered trademark of Advanced Micro Devices, Inc.
* Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc.
* All Rights Reserved.
*
* To receive a copy of this documentation, send an email to openpic@amd.com.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#ifndef _LINUX_OPENPIC_H
#define _LINUX_OPENPIC_H
#ifdef __KERNEL__
#include <linux/config.h>
/*
* OpenPIC supports up to 2048 interrupt sources and up to 32 processors
*/
#define OPENPIC_MAX_SOURCES 2048
#define OPENPIC_MAX_PROCESSORS 32
#define OPENPIC_MAX_ISU 32
#define OPENPIC_NUM_TIMERS 4
#define OPENPIC_NUM_IPI 4
#define OPENPIC_NUM_PRI 16
#define OPENPIC_NUM_VECTORS OPENPIC_MAX_SOURCES
/*
* OpenPIC Registers are 32 bits and aligned on 128 bit boundaries
*/
typedef struct _OpenPIC_Reg {
u_int Reg; /* Little endian! */
char Pad[0xc];
} OpenPIC_Reg;
/*
* Per Processor Registers
*/
typedef struct _OpenPIC_Processor {
/*
* Private Shadow Registers (for SLiC backwards compatibility)
*/
u_int IPI0_Dispatch_Shadow; /* Write Only */
char Pad1[0x4];
u_int IPI0_Vector_Priority_Shadow; /* Read/Write */
char Pad2[0x34];
/*
* Interprocessor Interrupt Command Ports
*/
OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI]; /* Write Only */
/*
* Current Task Priority Register
*/
OpenPIC_Reg _Current_Task_Priority; /* Read/Write */
char Pad3[0x10];
/*
* Interrupt Acknowledge Register
*/
OpenPIC_Reg _Interrupt_Acknowledge; /* Read Only */
/*
* End of Interrupt (EOI) Register
*/
OpenPIC_Reg _EOI; /* Read/Write */
char Pad5[0xf40];
} OpenPIC_Processor;
/*
* Timer Registers
*/
typedef struct _OpenPIC_Timer {
OpenPIC_Reg _Current_Count; /* Read Only */
OpenPIC_Reg _Base_Count; /* Read/Write */
OpenPIC_Reg _Vector_Priority; /* Read/Write */
OpenPIC_Reg _Destination; /* Read/Write */
} OpenPIC_Timer;
/*
* Global Registers
*/
typedef struct _OpenPIC_Global {
/*
* Feature Reporting Registers
*/
OpenPIC_Reg _Feature_Reporting0; /* Read Only */
OpenPIC_Reg _Feature_Reporting1; /* Future Expansion */
/*
* Global Configuration Registers
*/
OpenPIC_Reg _Global_Configuration0; /* Read/Write */
OpenPIC_Reg _Global_Configuration1; /* Future Expansion */
/*
* Vendor Specific Registers
*/
OpenPIC_Reg _Vendor_Specific[4];
/*
* Vendor Identification Register
*/
OpenPIC_Reg _Vendor_Identification; /* Read Only */
/*
* Processor Initialization Register
*/
OpenPIC_Reg _Processor_Initialization; /* Read/Write */
/*
* IPI Vector/Priority Registers
*/
OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI]; /* Read/Write */
/*
* Spurious Vector Register
*/
OpenPIC_Reg _Spurious_Vector; /* Read/Write */
/*
* Global Timer Registers
*/
OpenPIC_Reg _Timer_Frequency; /* Read/Write */
OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS];
char Pad1[0xee00];
} OpenPIC_Global;
/*
* Interrupt Source Registers
*/
typedef struct _OpenPIC_Source {
OpenPIC_Reg _Vector_Priority; /* Read/Write */
OpenPIC_Reg _Destination; /* Read/Write */
} OpenPIC_Source, *OpenPIC_SourcePtr;
/*
* OpenPIC Register Map
*/
struct OpenPIC {
char Pad1[0x1000];
/*
* Global Registers
*/
OpenPIC_Global Global;
/*
* Interrupt Source Configuration Registers
*/
OpenPIC_Source Source[OPENPIC_MAX_SOURCES];
/*
* Per Processor Registers
*/
OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS];
};
/*
* Current Task Priority Register
*/
#define OPENPIC_CURRENT_TASK_PRIORITY_MASK 0x0000000f
/*
* Who Am I Register
*/
#define OPENPIC_WHO_AM_I_ID_MASK 0x0000001f
/*
* Feature Reporting Register 0
*/
#define OPENPIC_FEATURE_LAST_SOURCE_MASK 0x07ff0000
#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT 16
#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK 0x00001f00
#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT 8
#define OPENPIC_FEATURE_VERSION_MASK 0x000000ff
/*
* Global Configuration Register 0
*/
#define OPENPIC_CONFIG_RESET 0x80000000
#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE 0x20000000
#define OPENPIC_CONFIG_BASE_MASK 0x000fffff
/*
* Vendor Identification Register
*/
#define OPENPIC_VENDOR_ID_STEPPING_MASK 0x00ff0000
#define OPENPIC_VENDOR_ID_STEPPING_SHIFT 16
#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00
#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT 8
#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK 0x000000ff
/*
* Vector/Priority Registers
*/
#define OPENPIC_MASK 0x80000000
#define OPENPIC_ACTIVITY 0x40000000 /* Read Only */
#define OPENPIC_PRIORITY_MASK 0x000f0000
#define OPENPIC_PRIORITY_SHIFT 16
#define OPENPIC_VECTOR_MASK 0x000007ff
/*
* Interrupt Source Registers
*/
#define OPENPIC_POLARITY_POSITIVE 0x00800000
#define OPENPIC_POLARITY_NEGATIVE 0x00000000
#define OPENPIC_POLARITY_MASK 0x00800000
#define OPENPIC_SENSE_LEVEL 0x00400000
#define OPENPIC_SENSE_EDGE 0x00000000
#define OPENPIC_SENSE_MASK 0x00400000
/*
* Timer Registers
*/
#define OPENPIC_COUNT_MASK 0x7fffffff
#define OPENPIC_TIMER_TOGGLE 0x80000000
#define OPENPIC_TIMER_COUNT_INHIBIT 0x80000000
/*
* Aliases to make life simpler
*/
/* Per Processor Registers */
#define IPI_Dispatch(i) _IPI_Dispatch[i].Reg
#define Current_Task_Priority _Current_Task_Priority.Reg
#define Interrupt_Acknowledge _Interrupt_Acknowledge.Reg
#define EOI _EOI.Reg
/* Global Registers */
#define Feature_Reporting0 _Feature_Reporting0.Reg
#define Feature_Reporting1 _Feature_Reporting1.Reg
#define Global_Configuration0 _Global_Configuration0.Reg
#define Global_Configuration1 _Global_Configuration1.Reg
#define Vendor_Specific(i) _Vendor_Specific[i].Reg
#define Vendor_Identification _Vendor_Identification.Reg
#define Processor_Initialization _Processor_Initialization.Reg
#define IPI_Vector_Priority(i) _IPI_Vector_Priority[i].Reg
#define Spurious_Vector _Spurious_Vector.Reg
#define Timer_Frequency _Timer_Frequency.Reg
/* Timer Registers */
#define Current_Count _Current_Count.Reg
#define Base_Count _Base_Count.Reg
#define Vector_Priority _Vector_Priority.Reg
#define Destination _Destination.Reg
/* Interrupt Source Registers */
#define Vector_Priority _Vector_Priority.Reg
#define Destination _Destination.Reg
#endif /* __KERNEL__ */
#endif /* _LINUX_OPENPIC_H */
/*
* 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
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <asm/ptrace.h>
#include <asm/signal.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include "open_pic.h"
#include "open_pic_defs.h"
void* OpenPIC2_Addr;
static volatile struct OpenPIC *OpenPIC2 = NULL;
extern u_int OpenPIC_NumInitSenses;
extern u_char *OpenPIC_InitSenses;
static u_int NumSources;
static int NumISUs;
static int open_pic2_irq_offset;
static OpenPIC_SourcePtr ISU2[OPENPIC_MAX_ISU];
unsigned int openpic2_vec_spurious;
/*
* Accesses to the current processor's openpic registers
* U3 secondary openpic has only one output
*/
#define THIS_CPU Processor[0]
#define DECL_THIS_CPU
#define CHECK_THIS_CPU
#define GET_ISU(source) ISU2[(source) >> 4][(source) & 0xf]
static inline u_int openpic2_read(volatile u_int *addr)
{
u_int val;
val = in_be32(addr);
return val;
}
static inline void openpic2_write(volatile u_int *addr, u_int val)
{
out_be32(addr, val);
}
static inline u_int openpic2_readfield(volatile u_int *addr, u_int mask)
{
u_int val = openpic2_read(addr);
return val & mask;
}
static inline void openpic2_writefield(volatile u_int *addr, u_int mask,
u_int field)
{
u_int val = openpic2_read(addr);
openpic2_write(addr, (val & ~mask) | (field & mask));
}
static inline void openpic2_clearfield(volatile u_int *addr, u_int mask)
{
openpic2_writefield(addr, mask, 0);
}
static inline void openpic2_setfield(volatile u_int *addr, u_int mask)
{
openpic2_writefield(addr, mask, mask);
}
static void openpic2_safe_writefield(volatile u_int *addr, u_int mask,
u_int field)
{
unsigned int loops = 100000;
openpic2_setfield(addr, OPENPIC_MASK);
while (openpic2_read(addr) & OPENPIC_ACTIVITY) {
if (!loops--) {
printk(KERN_ERR "openpic2_safe_writefield timeout\n");
break;
}
}
openpic2_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
}
static inline void openpic2_reset(void)
{
openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
OPENPIC_CONFIG_RESET);
}
static void openpic2_disable_8259_pass_through(void)
{
openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
}
/*
* Find out the current interrupt
*/
static u_int openpic2_irq(void)
{
u_int vec;
DECL_THIS_CPU;
CHECK_THIS_CPU;
vec = openpic2_readfield(&OpenPIC2->THIS_CPU.Interrupt_Acknowledge,
OPENPIC_VECTOR_MASK);
return vec;
}
static void openpic2_eoi(void)
{
DECL_THIS_CPU;
CHECK_THIS_CPU;
openpic2_write(&OpenPIC2->THIS_CPU.EOI, 0);
/* Handle PCI write posting */
(void)openpic2_read(&OpenPIC2->THIS_CPU.EOI);
}
static inline u_int openpic2_get_priority(void)
{
DECL_THIS_CPU;
CHECK_THIS_CPU;
return openpic2_readfield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
OPENPIC_CURRENT_TASK_PRIORITY_MASK);
}
static void openpic2_set_priority(u_int pri)
{
DECL_THIS_CPU;
CHECK_THIS_CPU;
openpic2_writefield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
}
/*
* Get/set the spurious vector
*/
static inline u_int openpic2_get_spurious(void)
{
return openpic2_readfield(&OpenPIC2->Global.Spurious_Vector,
OPENPIC_VECTOR_MASK);
}
static void openpic2_set_spurious(u_int vec)
{
openpic2_writefield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
vec);
}
/*
* Enable/disable an external interrupt source
*
* Externally called, irq is an offseted system-wide interrupt number
*/
static void openpic2_enable_irq(u_int irq)
{
unsigned int loops = 100000;
openpic2_clearfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, OPENPIC_MASK);
/* make sure mask gets to controller before we return to user */
do {
if (!loops--) {
printk(KERN_ERR "openpic_enable_irq timeout\n");
break;
}
mb(); /* sync is probably useless here */
} while(openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
OPENPIC_MASK));
}
static void openpic2_disable_irq(u_int irq)
{
u32 vp;
unsigned int loops = 100000;
openpic2_setfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
OPENPIC_MASK);
/* make sure mask gets to controller before we return to user */
do {
if (!loops--) {
printk(KERN_ERR "openpic_disable_irq timeout\n");
break;
}
mb(); /* sync is probably useless here */
vp = openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
OPENPIC_MASK | OPENPIC_ACTIVITY);
} while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
}
/*
* Initialize an interrupt source (and disable it!)
*
* irq: OpenPIC interrupt number
* pri: interrupt source priority
* vec: the vector it will produce
* pol: polarity (1 for positive, 0 for negative)
* sense: 1 for level, 0 for edge
*/
static void openpic2_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
{
openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority,
OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
(pri << OPENPIC_PRIORITY_SHIFT) | vec |
(pol ? OPENPIC_POLARITY_POSITIVE :
OPENPIC_POLARITY_NEGATIVE) |
(sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
}
/*
* Map an interrupt source to one or more CPUs
*/
static void openpic2_mapirq(u_int irq, u_int physmask)
{
openpic2_write(&GET_ISU(irq).Destination, physmask);
}
/*
* Set the sense for an interrupt source (and disable it!)
*
* sense: 1 for level, 0 for edge
*/
static inline void openpic2_set_sense(u_int irq, int sense)
{
openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority,
OPENPIC_SENSE_LEVEL,
(sense ? OPENPIC_SENSE_LEVEL : 0));
}
static void openpic2_end_irq(unsigned int irq_nr)
{
openpic2_eoi();
}
int openpic2_get_irq(struct pt_regs *regs)
{
int irq = openpic2_irq();
if (irq == openpic2_vec_spurious)
return -1;
return irq + open_pic2_irq_offset;
}
struct hw_interrupt_type open_pic2 = {
" OpenPIC2 ",
NULL,
NULL,
openpic2_enable_irq,
openpic2_disable_irq,
NULL,
openpic2_end_irq,
};
void __init openpic2_init(int offset)
{
u_int t, i;
const char *version;
if (!OpenPIC2_Addr) {
printk(KERN_INFO "No OpenPIC2 found !\n");
return;
}
OpenPIC2 = (volatile struct OpenPIC *)OpenPIC2_Addr;
ppc64_boot_msg(0x20, "OpenPic U3 Init");
t = openpic2_read(&OpenPIC2->Global.Feature_Reporting0);
switch (t & OPENPIC_FEATURE_VERSION_MASK) {
case 1:
version = "1.0";
break;
case 2:
version = "1.2";
break;
case 3:
version = "1.3";
break;
default:
version = "?";
break;
}
printk(KERN_INFO "OpenPIC (U3) Version %s\n", version);
open_pic2_irq_offset = offset;
for (i=0; i<128; i+=0x10) {
ISU2[i>>4] = &((struct OpenPIC *)OpenPIC2_Addr)->Source[i];
NumISUs++;
}
NumSources = NumISUs * 0x10;
openpic2_vec_spurious = NumSources;
openpic2_set_priority(0xf);
/* Init all external sources */
for (i = 0; i < NumSources; i++) {
int pri, sense;
/* the bootloader may have left it enabled (bad !) */
openpic2_disable_irq(i+offset);
pri = 8;
sense = (i < OpenPIC_NumInitSenses) ? OpenPIC_InitSenses[i]: 1;
if (sense)
irq_desc[i+offset].status = IRQ_LEVEL;
/* Enabled, Priority 8 or 9 */
openpic2_initirq(i, pri, i, !sense, sense);
/* Processor 0 */
openpic2_mapirq(i, 0x1);
}
/* Init descriptors */
for (i = offset; i < NumSources + offset; i++)
irq_desc[i].handler = &open_pic2;
/* Initialize the spurious interrupt */
openpic2_set_spurious(openpic2_vec_spurious);
openpic2_set_priority(0);
openpic2_disable_8259_pass_through();
ppc64_boot_msg(0x25, "OpenPic U3 Done");
}
......@@ -42,7 +42,7 @@
#include <asm/iommu.h>
#include <asm/rtas.h>
#include "open_pic.h"
#include "mpic.h"
#include "pci.h"
/* RTAS tokens */
......@@ -54,6 +54,7 @@ static int ibm_write_pci_config;
static int s7a_workaround;
extern unsigned long pci_probe_only;
extern struct mpic *pSeries_mpic;
static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
{
......@@ -399,9 +400,9 @@ unsigned long __init find_and_init_phbs(void)
pci_process_bridge_OF_ranges(phb, node);
pci_setup_phb_io(phb, index == 0);
if (naca->interrupt_controller == IC_OPEN_PIC) {
if (naca->interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
int addr = root_size_cells * (index + 2) - 1;
openpic_setup_ISU(index, opprop[addr]);
mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
}
index++;
......
......@@ -61,19 +61,18 @@
#include <asm/nvram.h>
#include "i8259.h"
#include "open_pic.h"
#include <asm/xics.h>
#include <asm/ppcdebug.h>
#include <asm/cputable.h>
#include "mpic.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
extern void pSeries_init_openpic(void);
extern void find_and_init_phbs(void);
extern void pSeries_final_fixup(void);
......@@ -91,6 +90,9 @@ extern unsigned long loops_per_jiffy;
extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
static volatile void __iomem * chrp_int_ack_special;
struct mpic *pSeries_mpic;
void pSeries_get_cpuinfo(struct seq_file *m)
{
struct device_node *root;
......@@ -120,15 +122,86 @@ static void __init fwnmi_init(void)
fwnmi_active = 1;
}
static void __init pSeries_setup_arch(void)
static int pSeries_irq_cascade(struct pt_regs *regs, void *data)
{
if (chrp_int_ack_special)
return readb(chrp_int_ack_special);
else
return i8259_irq(smp_processor_id());
}
static void __init pSeries_init_mpic(void)
{
unsigned int *addrp;
unsigned char* chrp_int_ack_special = NULL;
struct device_node *np;
int i;
/* All ISUs are setup, complete initialization */
mpic_init(pSeries_mpic);
/* Check what kind of cascade ACK we have */
if (!(np = of_find_node_by_name(NULL, "pci"))
|| !(addrp = (unsigned int *)
get_property(np, "8259-interrupt-acknowledge", NULL)))
printk(KERN_ERR "Cannot find pci to get ack address\n");
else
chrp_int_ack_special = (unsigned char *)
ioremap(addrp[prom_n_addr_cells(np)-1], 1);
of_node_put(np);
/* Setup the legacy interrupts & controller */
for (i = 0; i < NUM_ISA_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
i8259_init(0);
/* Hook cascade to mpic */
mpic_setup_cascade(NUM_ISA_INTERRUPTS, pSeries_irq_cascade, NULL);
}
static void __init pSeries_setup_mpic(void)
{
struct device_node *root;
unsigned int *opprop;
unsigned long openpic_addr = 0;
unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS];
struct device_node *root;
int irq_count;
/* Find the Open PIC if present */
root = of_find_node_by_path("/");
opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL);
if (opprop != 0) {
int n = prom_n_addr_cells(root);
for (openpic_addr = 0; n > 0; --n)
openpic_addr = (openpic_addr << 32) + *opprop++;
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
}
of_node_put(root);
BUG_ON(openpic_addr == 0);
/* Get the sense values from OF */
prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS);
/* Setup the openpic driver */
irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY,
16, 16, irq_count, /* isu size, irq offset, irq count */
NR_IRQS - 4, /* ipi offset */
senses, irq_count, /* sense & sense size */
" MPIC ");
}
static void __init pSeries_setup_arch(void)
{
/* Fixup ppc_md depending on the type of interrupt controller */
if (naca->interrupt_controller == IC_OPEN_PIC) {
ppc_md.init_IRQ = pSeries_init_openpic;
ppc_md.get_irq = openpic_get_irq;
ppc_md.init_IRQ = pSeries_init_mpic;
ppc_md.get_irq = mpic_get_irq;
/* Allocate the mpic now, so that find_and_init_phbs() can
* fill the ISUs */
pSeries_setup_mpic();
} else {
ppc_md.init_IRQ = xics_init_IRQ;
ppc_md.get_irq = xics_get_irq;
......@@ -156,21 +229,6 @@ static void __init pSeries_setup_arch(void)
eeh_init();
find_and_init_phbs();
/* Find the Open PIC if present */
root = of_find_node_by_path("/");
opprop = (unsigned int *) get_property(root,
"platform-open-pic", NULL);
if (opprop != 0) {
int n = prom_n_addr_cells(root);
unsigned long openpic;
for (openpic = 0; n > 0; --n)
openpic = (openpic << 32) + *opprop++;
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic);
OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE);
}
of_node_put(root);
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
......
......@@ -72,6 +72,7 @@
#include <asm/lmb.h>
#include "pmac.h"
#include "mpic.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
......@@ -319,29 +320,9 @@ void __init pmac_init_early(void)
DBG(" <- pmac_init_early\n");
}
extern void* OpenPIC_Addr;
extern void* OpenPIC2_Addr;
extern u_int OpenPIC_NumInitSenses;
extern u_char *OpenPIC_InitSenses;
extern void openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
int programmer_switch_irq);
extern void openpic2_init(int offset);
extern int openpic_get_irq(struct pt_regs *regs);
extern int openpic2_get_irq(struct pt_regs *regs);
static int pmac_cascade_irq = -1;
static irqreturn_t pmac_u3_do_cascade(int cpl, void *dev_id, struct pt_regs *regs)
static int pmac_u3_cascade(struct pt_regs *regs, void *data)
{
int irq;
for (;;) {
irq = openpic2_get_irq(regs);
if (irq == -1)
break;
ppc_irq_dispatch_handler(regs, irq);
}
return IRQ_HANDLED;
return mpic_get_one_irq((struct mpic *)data, regs);
}
static __init void pmac_init_IRQ(void)
......@@ -349,6 +330,7 @@ static __init void pmac_init_IRQ(void)
struct device_node *irqctrler = NULL;
struct device_node *irqctrler2 = NULL;
struct device_node *np = NULL;
struct mpic *mpic1, *mpic2;
/* We first try to detect Apple's new Core99 chipset, since mac-io
* is quite different on those machines and contains an IBM MPIC2.
......@@ -368,44 +350,37 @@ static __init void pmac_init_IRQ(void)
(unsigned int)irqctrler->addrs[0].address);
prom_get_irq_senses(senses, 0, 128);
OpenPIC_InitSenses = senses;
OpenPIC_NumInitSenses = 128;
OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
irqctrler->addrs[0].size);
openpic_init(1, 0, NULL, -1);
mpic1 = mpic_alloc(irqctrler->addrs[0].address,
MPIC_PRIMARY | MPIC_WANTS_RESET,
0, 0, 128, 256, senses, 128, " K2-MPIC ");
BUG_ON(mpic1 == NULL);
mpic_init(mpic1);
if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&
irqctrler2->n_addrs > 0) {
printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",
(u32)irqctrler2->addrs[0].address,
irqctrler2->intrs[0].line);
pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);
OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address,
irqctrler2->addrs[0].size);
prom_get_irq_senses(senses, 128, 128 + 128);
OpenPIC_InitSenses = senses;
OpenPIC_NumInitSenses = 128;
openpic2_init(128);
pmac_cascade_irq = irqctrler2->intrs[0].line;
/* We don't need to set MPIC_BROKEN_U3 here since we don't have
* hypertransport interrupts routed to it
*/
mpic2 = mpic_alloc(irqctrler2->addrs[0].address,
MPIC_BIG_ENDIAN | MPIC_WANTS_RESET,
0, 128, 128, 0, senses, 128, " U3-MPIC ");
BUG_ON(mpic2 == NULL);
mpic_init(mpic2);
mpic_setup_cascade(irqctrler2->intrs[0].line,
pmac_u3_cascade, mpic2);
}
}
of_node_put(irqctrler);
of_node_put(irqctrler2);
}
/* We cannot do request_irq too early ... Right now, we get the
* cascade as a core_initcall, which should be fine for our needs
*/
static int __init pmac_irq_cascade_init(void)
{
if (request_irq(pmac_cascade_irq, pmac_u3_do_cascade, 0,
"U3->K2 Cascade", NULL))
printk(KERN_ERR "Unable to get OpenPIC IRQ for cascade\n");
return 0;
}
core_initcall(pmac_irq_cascade_init);
static void __init pmac_progress(char *s, unsigned short hex)
{
if (sccdbg) {
......@@ -463,7 +438,7 @@ struct machdep_calls __initdata pmac_md = {
.init_early = pmac_init_early,
.get_cpuinfo = pmac_show_cpuinfo,
.init_IRQ = pmac_init_IRQ,
.get_irq = openpic_get_irq,
.get_irq = mpic_get_irq,
.pcibios_fixup = pmac_pcibios_fixup,
.restart = pmac_restart,
.power_off = pmac_power_off,
......
......@@ -32,6 +32,7 @@
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/irq.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
......@@ -48,14 +49,13 @@
#include <asm/cacheflush.h>
#include <asm/keylargo.h>
#include "open_pic.h"
#include "mpic.h"
extern void pmac_secondary_start_1(void);
extern void pmac_secondary_start_2(void);
extern void pmac_secondary_start_3(void);
extern void smp_openpic_message_pass(int target, int msg);
extern struct smp_ops_t *smp_ops;
static int __init smp_core99_probe(void)
......@@ -75,7 +75,7 @@ static int __init smp_core99_probe(void)
printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus);
if (ncpus > 1)
openpic_request_IPIs();
mpic_request_ipis();
return ncpus;
}
......@@ -138,8 +138,8 @@ static void __init smp_core99_kick_cpu(int nr)
static void __init smp_core99_setup_cpu(int cpu_nr)
{
/* Setup openpic */
do_openpic_setup_cpu();
/* Setup MPIC */
mpic_setup_this_cpu();
if (cpu_nr == 0) {
extern void g5_phy_disable_cpu1(void);
......@@ -157,7 +157,7 @@ extern void smp_generic_give_timebase(void);
extern void smp_generic_take_timebase(void);
struct smp_ops_t core99_smp_ops __pmacdata = {
.message_pass = smp_openpic_message_pass,
.message_pass = smp_mpic_message_pass,
.probe = smp_core99_probe,
.kick_cpu = smp_core99_kick_cpu,
.setup_cpu = smp_core99_setup_cpu,
......
......@@ -52,7 +52,6 @@
#include <asm/btext.h>
#include <asm/sections.h>
#include <asm/machdep.h>
#include "open_pic.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
......@@ -1092,8 +1091,7 @@ prom_n_size_cells(struct device_node* np)
* Work out the sense (active-low level / active-high edge)
* of each interrupt from the device tree.
*/
void __init
prom_get_irq_senses(unsigned char *senses, int off, int max)
void __init prom_get_irq_senses(unsigned char *senses, int off, int max)
{
struct device_node *np;
int i, j;
......@@ -1105,7 +1103,9 @@ prom_get_irq_senses(unsigned char *senses, int off, int max)
for (j = 0; j < np->n_intrs; j++) {
i = np->intrs[j].line;
if (i >= off && i < max)
senses[i-off] = np->intrs[j].sense;
senses[i-off] = np->intrs[j].sense ?
IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE :
IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE;
}
}
}
......
......@@ -51,7 +51,6 @@
#include <asm/btext.h>
#include <asm/sections.h>
#include <asm/machdep.h>
#include "open_pic.h"
#ifdef CONFIG_LOGO_LINUX_CLUT224
#include <linux/linux_logo.h>
......
......@@ -48,11 +48,12 @@
#include <asm/iSeries/HvCallCfg.h>
#include <asm/time.h>
#include <asm/ppcdebug.h>
#include "open_pic.h"
#include <asm/machdep.h>
#include <asm/xics.h>
#include <asm/cputable.h>
#include <asm/system.h>
#include "mpic.h"
#include <asm/rtas.h>
#include <asm/plpar_wrappers.h>
......@@ -194,7 +195,7 @@ void __init smp_init_iSeries(void)
#endif
#ifdef CONFIG_PPC_MULTIPLATFORM
void smp_openpic_message_pass(int target, int msg)
void smp_mpic_message_pass(int target, int msg)
{
/* make sure we're sending something that translates to an IPI */
if ( msg > 0x3 ){
......@@ -205,33 +206,36 @@ void smp_openpic_message_pass(int target, int msg)
switch ( target )
{
case MSG_ALL:
openpic_cause_IPI(msg, 0xffffffff);
mpic_send_ipi(msg, 0xffffffff);
break;
case MSG_ALL_BUT_SELF:
openpic_cause_IPI(msg,
0xffffffff & ~(1 << smp_processor_id()));
mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id()));
break;
default:
openpic_cause_IPI(msg, 1<<target);
mpic_send_ipi(msg, 1 << target);
break;
}
}
static int __init smp_openpic_probe(void)
int __init smp_mpic_probe(void)
{
int nr_cpus;
DBG("smp_mpic_probe()...\n");
nr_cpus = cpus_weight(cpu_possible_map);
DBG("nr_cpus: %d\n", nr_cpus);
if (nr_cpus > 1)
openpic_request_IPIs();
mpic_request_ipis();
return nr_cpus;
}
static void __devinit smp_openpic_setup_cpu(int cpu)
void __devinit smp_mpic_setup_cpu(int cpu)
{
do_openpic_setup_cpu();
mpic_setup_this_cpu();
}
#endif /* CONFIG_PPC_MULTIPLATFORM */
......@@ -532,11 +536,11 @@ static void __devinit pSeries_take_timebase(void)
spin_unlock(&timebase_lock);
}
static struct smp_ops_t pSeries_openpic_smp_ops = {
.message_pass = smp_openpic_message_pass,
.probe = smp_openpic_probe,
static struct smp_ops_t pSeries_mpic_smp_ops = {
.message_pass = smp_mpic_message_pass,
.probe = smp_mpic_probe,
.kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_openpic_setup_cpu,
.setup_cpu = smp_mpic_setup_cpu,
};
static struct smp_ops_t pSeries_xics_smp_ops = {
......@@ -554,7 +558,7 @@ void __init smp_init_pSeries(void)
DBG(" -> smp_init_pSeries()\n");
if (naca->interrupt_controller == IC_OPEN_PIC)
smp_ops = &pSeries_openpic_smp_ops;
smp_ops = &pSeries_mpic_smp_ops;
else
smp_ops = &pSeries_xics_smp_ops;
......
......@@ -578,7 +578,7 @@ static int __init xics_setup_i8259(void)
no_action, 0, "8259 cascade", NULL))
printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 "
"cascade\n");
i8259_init();
i8259_init(0);
}
return 0;
}
......
......@@ -20,6 +20,19 @@
/* this number is used when no interrupt has been assigned */
#define NO_IRQ (-1)
/*
* These constants are used for passing information about interrupt
* signal polarity and level/edge sensing to the low-level PIC chip
* drivers.
*/
#define IRQ_SENSE_MASK 0x1
#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */
#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */
#define IRQ_POLARITY_MASK 0x2
#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */
#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */
#define get_irq_desc(irq) (&irq_desc[(irq)])
/* Define a way to iterate across irqs. */
......
......@@ -67,6 +67,10 @@ extern int query_cpu_stopped(unsigned int pcpu);
extern int smt_enabled_at_boot;
extern int smp_mpic_probe(void);
extern void smp_mpic_setup_cpu(int cpu);
extern void smp_mpic_message_pass(int target, int msg);
#endif /* __ASSEMBLY__ */
#endif /* !(_PPC64_SMP_H) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment