Commit f9bd170a authored by Paul Mackerras's avatar Paul Mackerras

powerpc: Merge i8259.c into arch/powerpc/sysdev

This changes the parameters for i8259_init so that it takes two
parameters: a physical address for generating an interrupt
acknowledge cycle, and an interrupt number offset.  i8259_init
now sets the irq_desc[] for its interrupts; all the callers
were doing this, and that code is gone now.  This also defines
a CONFIG_PPC_I8259 symbol to select i8259.o for inclusion, and
makes the platforms that need it select that symbol.
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 25635c71
......@@ -275,11 +275,13 @@ endchoice
config PPC_PSERIES
depends on PPC_MULTIPLATFORM && PPC64
bool " IBM pSeries & new (POWER5-based) iSeries"
select PPC_I8259
default y
config PPC_CHRP
bool " Common Hardware Reference Platform (CHRP) based machines"
depends on PPC_MULTIPLATFORM && PPC32
select PPC_I8259
select PPC_INDIRECT_PCI
default y
......@@ -298,6 +300,7 @@ config PPC_PMAC64
config PPC_PREP
bool " PowerPC Reference Platform (PReP) based machines"
depends on PPC_MULTIPLATFORM && PPC32
select PPC_I8259
select PPC_INDIRECT_PCI
default y
......@@ -628,6 +631,7 @@ menu "Bus options"
config ISA
bool "Support for ISA-bus hardware"
depends on PPC_PREP || PPC_CHRP
select PPC_I8259
help
Find out whether you have ISA slots on your motherboard. ISA is the
name of a bus system, i.e. the way the CPU talks to the other stuff
......@@ -640,6 +644,11 @@ config GENERIC_ISA_DMA
depends on PPC64 || POWER4 || 6xx && !CPM2
default y
config PPC_I8259
bool
default y if 85xx
default n
config PPC_INDIRECT_PCI
bool
depends on PCI
......@@ -679,6 +688,7 @@ config MPC83xx_PCI2
config PCI_QSPAN
bool "QSpan PCI"
depends on !4xx && !CPM2 && 8xx
select PPC_I8259
help
Say Y here if you have a system based on a Motorola 8xx-series
embedded processor with a QSPAN PCI interface, otherwise say N.
......
......@@ -48,6 +48,7 @@ config EV64260
config LOPEC
bool "Motorola-LoPEC"
select PPC_I8259
config MVME5100
bool "Motorola-MVME5100"
......@@ -55,6 +56,7 @@ config MVME5100
config PPLUS
bool "Motorola-PowerPlus"
select PPC_I8259
select PPC_INDIRECT_PCI
config PRPMC750
......@@ -67,12 +69,14 @@ config PRPMC800
config SANDPOINT
bool "Motorola-Sandpoint"
select PPC_I8259
help
Select SANDPOINT if configuring for a Motorola Sandpoint X3
(any flavor).
config RADSTONE_PPC7D
bool "Radstone Technology PPC7D board"
select PPC_I8259
config PAL4
bool "SBS-Palomar4"
......@@ -307,6 +311,7 @@ config HARRIER_STORE_GATHERING
config MVME5100_IPMC761_PRESENT
bool "MVME5100 configured with an IPMC761"
depends on MVME5100
select PPC_I8259
config SPRUCE_BAUD_33M
bool "Spruce baud clock support"
......
......@@ -87,7 +87,6 @@ extern int pSeries_machine_check_exception(struct pt_regs *regs);
static void pseries_shared_idle(void);
static void pseries_dedicated_idle(void);
static volatile void __iomem * chrp_int_ack_special;
struct mpic *pSeries_mpic;
void pSeries_show_cpuinfo(struct seq_file *m)
......@@ -119,19 +118,11 @@ static void __init fwnmi_init(void)
fwnmi_active = 1;
}
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(regs);
}
static void __init pSeries_init_mpic(void)
{
unsigned int *addrp;
struct device_node *np;
int i;
unsigned long intack = 0;
/* All ISUs are setup, complete initialization */
mpic_init(pSeries_mpic);
......@@ -142,16 +133,14 @@ static void __init pSeries_init_mpic(void)
get_property(np, "8259-interrupt-acknowledge", NULL)))
printk(KERN_ERR "Cannot find pci to get ack address\n");
else
chrp_int_ack_special = ioremap(addrp[prom_n_addr_cells(np)-1], 1);
intack = addrp[prom_n_addr_cells(np)-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);
i8259_init(intack, 0);
/* Hook cascade to mpic */
mpic_setup_cascade(NUM_ISA_INTERRUPTS, pSeries_irq_cascade, NULL);
mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL);
}
static void __init pSeries_setup_mpic(void)
......
obj-$(CONFIG_MPIC) += mpic.o
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_I8259) += i8259.o
/*
* i8259 interrupt controller driver.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/i8259.h>
static volatile unsigned char *pci_intack; /* RO, gives us the irq vector */
static volatile void __iomem *pci_intack; /* RO, gives us the irq vector */
unsigned char cached_8259[2] = { 0xff, 0xff };
static unsigned char cached_8259[2] = { 0xff, 0xff };
#define cached_A1 (cached_8259[0])
#define cached_21 (cached_8259[1])
static DEFINE_SPINLOCK(i8259_lock);
int i8259_pic_irq_offset;
static int i8259_pic_irq_offset;
/*
* Acknowledge the IRQ using either the PCI host bridge's interrupt
......@@ -20,8 +28,7 @@ int i8259_pic_irq_offset;
* which is called. It should be noted that polling is broken on some
* IBM and Motorola PReP boxes so we must use the int-ack feature on them.
*/
int
i8259_irq(struct pt_regs *regs)
int i8259_irq(struct pt_regs *regs)
{
int irq;
......@@ -29,7 +36,7 @@ i8259_irq(struct pt_regs *regs)
/* Either int-ack or poll for the IRQ */
if (pci_intack)
irq = *pci_intack;
irq = readb(pci_intack);
else {
/* Perform an interrupt acknowledge cycle on controller 1. */
outb(0x0C, 0x20); /* prepare for poll */
......@@ -59,7 +66,12 @@ i8259_irq(struct pt_regs *regs)
}
spin_unlock(&i8259_lock);
return irq;
return irq + i8259_pic_irq_offset;
}
int i8259_irq_cascade(struct pt_regs *regs, void *unused)
{
return i8259_irq(regs);
}
static void i8259_mask_and_ack_irq(unsigned int irq_nr)
......@@ -67,20 +79,18 @@ static void i8259_mask_and_ack_irq(unsigned int irq_nr)
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
if ( irq_nr >= i8259_pic_irq_offset )
irq_nr -= i8259_pic_irq_offset;
if (irq_nr > 7) {
cached_A1 |= 1 << (irq_nr-8);
inb(0xA1); /* DUMMY */
outb(cached_A1,0xA1);
outb(0x20,0xA0); /* Non-specific EOI */
outb(0x20,0x20); /* Non-specific EOI to cascade */
outb(cached_A1, 0xA1);
outb(0x20, 0xA0); /* Non-specific EOI */
outb(0x20, 0x20); /* Non-specific EOI to cascade */
} else {
cached_21 |= 1 << irq_nr;
inb(0x21); /* DUMMY */
outb(cached_21,0x21);
outb(0x20,0x20); /* Non-specific EOI */
outb(cached_21, 0x21);
outb(0x20, 0x20); /* Non-specific EOI */
}
spin_unlock_irqrestore(&i8259_lock, flags);
}
......@@ -96,9 +106,8 @@ static void i8259_mask_irq(unsigned int irq_nr)
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
if ( irq_nr >= i8259_pic_irq_offset )
irq_nr -= i8259_pic_irq_offset;
if ( irq_nr < 8 )
if (irq_nr < 8)
cached_21 |= 1 << irq_nr;
else
cached_A1 |= 1 << (irq_nr-8);
......@@ -111,9 +120,8 @@ static void i8259_unmask_irq(unsigned int irq_nr)
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
if ( irq_nr >= i8259_pic_irq_offset )
irq_nr -= i8259_pic_irq_offset;
if ( irq_nr < 8 )
if (irq_nr < 8)
cached_21 &= ~(1 << irq_nr);
else
cached_A1 &= ~(1 << (irq_nr-8));
......@@ -169,12 +177,14 @@ static struct irqaction i8259_irqaction = {
* intack_addr - PCI interrupt acknowledge (real) address which will return
* the active irq from the 8259
*/
void __init
i8259_init(long intack_addr)
void __init i8259_init(unsigned long intack_addr, int offset)
{
unsigned long flags;
int i;
spin_lock_irqsave(&i8259_lock, flags);
i8259_pic_irq_offset = offset;
/* init master interrupt controller */
outb(0x11, 0x20); /* Start init sequence */
outb(0x00, 0x21); /* Vector base */
......@@ -198,11 +208,14 @@ i8259_init(long intack_addr)
spin_unlock_irqrestore(&i8259_lock, flags);
/* reserve our resources */
setup_irq( i8259_pic_irq_offset + 2, &i8259_irqaction);
setup_irq(offset + 2, &i8259_irqaction);
request_resource(&ioport_resource, &pic1_iores);
request_resource(&ioport_resource, &pic2_iores);
request_resource(&ioport_resource, &pic_edgectrl_iores);
if (intack_addr != 0)
pci_intack = ioremap(intack_addr, 1);
for (i = 0; i < NUM_ISA_INTERRUPTS; ++i)
irq_desc[offset + i].handler = &i8259_pic;
}
......@@ -589,6 +589,7 @@ config EV64260
config LOPEC
bool "Motorola-LoPEC"
select PPC_I8259
config MVME5100
bool "Motorola-MVME5100"
......@@ -596,6 +597,7 @@ config MVME5100
config PPLUS
bool "Motorola-PowerPlus"
select PPC_I8259
select PPC_INDIRECT_PCI
config PRPMC750
......@@ -608,12 +610,14 @@ config PRPMC800
config SANDPOINT
bool "Motorola-Sandpoint"
select PPC_I8259
help
Select SANDPOINT if configuring for a Motorola Sandpoint X3
(any flavor).
config RADSTONE_PPC7D
bool "Radstone Technology PPC7D board"
select PPC_I8259
config PAL4
bool "SBS-Palomar4"
......@@ -755,6 +759,7 @@ config CPM2
config PPC_CHRP
bool " Common Hardware Reference Platform (CHRP) based machines"
depends on PPC_MULTIPLATFORM
select PPC_I8259
select PPC_INDIRECT_PCI
default y
......@@ -772,6 +777,7 @@ config PPC_PMAC64
config PPC_PREP
bool " PowerPC Reference Platform (PReP) based machines"
depends on PPC_MULTIPLATFORM
select PPC_I8259
select PPC_INDIRECT_PCI
default y
......@@ -881,6 +887,7 @@ config HARRIER_STORE_GATHERING
config MVME5100_IPMC761_PRESENT
bool "MVME5100 configured with an IPMC761"
depends on MVME5100
select PPC_I8259
config SPRUCE_BAUD_33M
bool "Spruce baud clock support"
......@@ -1138,6 +1145,7 @@ menu "Bus options"
config ISA
bool "Support for ISA-bus hardware"
depends on PPC_PREP || PPC_CHRP
select PPC_I8259
help
Find out whether you have ISA slots on your motherboard. ISA is the
name of a bus system, i.e. the way the CPU talks to the other stuff
......@@ -1150,6 +1158,11 @@ config GENERIC_ISA_DMA
depends on POWER3 || POWER4 || 6xx && !CPM2
default y
config PPC_I8259
bool
default y if 85xx
default n
config PPC_INDIRECT_PCI
bool
depends on PCI
......@@ -1192,6 +1205,7 @@ config MPC83xx_PCI2
config PCI_QSPAN
bool "QSpan PCI"
depends on !4xx && !CPM2 && 8xx
select PPC_I8259
help
Say Y here if you have a system based on a Motorola 8xx-series
embedded processor with a QSPAN PCI interface, otherwise say N.
......
......@@ -173,10 +173,7 @@ mpc85xx_cds_init_IRQ(void)
#ifdef CONFIG_PCI
openpic_hookup_cascade(PIRQ0A, "82c59 cascade", i8259_irq);
for (i = 0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
i8259_init(0);
i8259_init(0, 0);
#endif
#ifdef CONFIG_CPM2
......
......@@ -436,9 +436,7 @@ void __init chrp_init_IRQ(void)
i8259_irq);
}
for (i = 0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
i8259_init(chrp_int_ack);
i8259_init(chrp_int_ack, 0);
#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
/* see if there is a keyboard in the device tree
......
......@@ -267,15 +267,11 @@ lopec_init_IRQ(void)
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
&i8259_irq);
/* Map i8259 interrupts */
for(i = 0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
/*
* The EPIC allows for a read in the range of 0xFEF00000 ->
* 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
*/
i8259_init(0xfef00000);
i8259_init(0xfef00000, 0);
}
static int __init
......
......@@ -223,11 +223,7 @@ mvme5100_init_IRQ(void)
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
&i8259_irq);
/* Map i8259 interrupts. */
for (i = 0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
i8259_init(0);
i8259_init(0, 0);
#else
openpic_init(0);
#endif
......
......@@ -665,10 +665,7 @@ static void __init pplus_init_IRQ(void)
ppc_md.get_irq = openpic_get_irq;
}
for (i = 0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
i8259_init(0);
i8259_init(0, 0);
if (ppc_md.progress)
ppc_md.progress("init_irq: exit", 0);
......
......@@ -954,11 +954,9 @@ prep_init_IRQ(void)
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
i8259_irq);
}
for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
irq_desc[i].handler = &i8259_pic;
if (have_residual_data) {
i8259_init(residual_isapic_addr());
i8259_init(residual_isapic_addr(), 0);
return;
}
......@@ -969,11 +967,11 @@ prep_init_IRQ(void)
if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA)
&& ((pci_did == PCI_DEVICE_ID_MOTOROLA_RAVEN)
|| (pci_did == PCI_DEVICE_ID_MOTOROLA_HAWK)))
i8259_init(0);
i8259_init(0, 0);
else
/* PCI interrupt ack address given in section 6.1.8 of the
* PReP specification. */
i8259_init(MPC10X_MAPA_PCI_INTACK_ADDR);
i8259_init(MPC10X_MAPA_PCI_INTACK_ADDR, 0);
}
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
......
......@@ -514,13 +514,9 @@ static void __init ppc7d_init_irq(void)
int irq;
pr_debug("%s\n", __FUNCTION__);
i8259_init(0);
i8259_init(0, 0);
mv64360_init_irq();
/* IRQ 0..15 are handled by the cascaded 8259's of the Ali1535 */
for (irq = 0; irq < 16; irq++) {
irq_desc[irq].handler = &i8259_pic;
}
/* IRQs 5,6,9,10,11,14,15 are level sensitive */
irq_desc[5].status |= IRQ_LEVEL;
irq_desc[6].status |= IRQ_LEVEL;
......
......@@ -493,19 +493,11 @@ sandpoint_init_IRQ(void)
openpic_hookup_cascade(sandpoint_is_x2 ? 17 : NUM_8259_INTERRUPTS, "82c59 cascade",
i8259_irq);
/*
* openpic_init() has set up irq_desc[16-31] to be openpic
* interrupts. We need to set irq_desc[0-15] to be i8259
* interrupts.
*/
for(i=0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
/*
* The EPIC allows for a read in the range of 0xFEF00000 ->
* 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
*/
i8259_init(0xfef00000);
i8259_init(0xfef00000, 0);
}
static unsigned long __init
......
......@@ -36,14 +36,12 @@ endif
endif
obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o
ifeq ($(CONFIG_8xx),y)
obj-$(CONFIG_PCI) += qspan_pci.o i8259.o
endif
obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o
obj-$(CONFIG_PPC_OF) += prom_init.o prom.o
obj-$(CONFIG_PPC_PMAC) += open_pic.o
obj-$(CONFIG_POWER4) += open_pic2.o
obj-$(CONFIG_PPC_CHRP) += open_pic.o i8259.o
obj-$(CONFIG_PPC_PREP) += open_pic.o i8259.o todc_time.o
obj-$(CONFIG_PPC_CHRP) += open_pic.o
obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o
obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o
obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o
obj-$(CONFIG_EBONY) += pci_auto.o todc_time.o
......@@ -51,7 +49,7 @@ obj-$(CONFIG_EV64260) += todc_time.o pci_auto.o
obj-$(CONFIG_CHESTNUT) += mv64360_pic.o pci_auto.o
obj-$(CONFIG_GEMINI) += open_pic.o
obj-$(CONFIG_GT64260) += gt64260_pic.o
obj-$(CONFIG_LOPEC) += i8259.o pci_auto.o todc_time.o
obj-$(CONFIG_LOPEC) += pci_auto.o todc_time.o
obj-$(CONFIG_HDPU) += pci_auto.o
obj-$(CONFIG_LUAN) += pci_auto.o todc_time.o
obj-$(CONFIG_KATANA) += pci_auto.o
......@@ -59,18 +57,17 @@ obj-$(CONFIG_MV64360) += mv64360_pic.o
obj-$(CONFIG_MV64X60) += mv64x60.o mv64x60_win.o
obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o \
pci_auto.o hawk_common.o
obj-$(CONFIG_MVME5100_IPMC761_PRESENT) += i8259.o
obj-$(CONFIG_OCOTEA) += pci_auto.o todc_time.o
obj-$(CONFIG_PAL4) += cpc700_pic.o
obj-$(CONFIG_POWERPMC250) += pci_auto.o
obj-$(CONFIG_PPLUS) += hawk_common.o open_pic.o i8259.o \
obj-$(CONFIG_PPLUS) += hawk_common.o open_pic.o \
todc_time.o pci_auto.o
obj-$(CONFIG_PRPMC750) += open_pic.o pci_auto.o \
hawk_common.o
obj-$(CONFIG_HARRIER) += harrier.o
obj-$(CONFIG_PRPMC800) += open_pic.o pci_auto.o
obj-$(CONFIG_RADSTONE_PPC7D) += i8259.o pci_auto.o
obj-$(CONFIG_SANDPOINT) += i8259.o pci_auto.o todc_time.o
obj-$(CONFIG_RADSTONE_PPC7D) += pci_auto.o
obj-$(CONFIG_SANDPOINT) += pci_auto.o todc_time.o
obj-$(CONFIG_SBC82xx) += todc_time.o
obj-$(CONFIG_SPRUCE) += cpc700_pic.o pci_auto.o \
todc_time.o
......@@ -92,7 +89,7 @@ obj-$(CONFIG_MPC10X_OPENPIC) += open_pic.o
obj-$(CONFIG_40x) += dcr.o
obj-$(CONFIG_BOOKE) += dcr.o
obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \
ppc_sys.o i8259.o mpc85xx_sys.o \
ppc_sys.o mpc85xx_sys.o \
mpc85xx_devices.o
ifeq ($(CONFIG_85xx),y)
obj-$(CONFIG_PCI) += pci_auto.o
......
......@@ -123,6 +123,11 @@ config MPIC
bool
default y
config PPC_I8259
depends on PPC_PSERIES
bool
default y
config BPA_IIC
depends on PPC_BPA
bool
......
......@@ -24,7 +24,7 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o
obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y)
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o
ifneq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
endif
......
/*
* c 2001 PPC64 Team, IBM Corp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/cache.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/ppcdebug.h>
#include "i8259.h"
unsigned char cached_8259[2] = { 0xff, 0xff };
#define cached_A1 (cached_8259[0])
#define cached_21 (cached_8259[1])
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(i8259_lock);
static int i8259_pic_irq_offset;
static int i8259_present;
int i8259_irq(int cpu)
{
int irq;
spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
/*
* Perform an interrupt acknowledge cycle on controller 1
*/
outb(0x0C, 0x20);
irq = inb(0x20) & 7;
if (irq == 2)
{
/*
* Interrupt is cascaded so perform interrupt
* acknowledge on controller 2
*/
outb(0x0C, 0xA0);
irq = (inb(0xA0) & 7) + 8;
}
else if (irq==7)
{
/*
* This may be a spurious interrupt
*
* Read the interrupt status register. If the most
* significant bit is not set then there is no valid
* interrupt
*/
outb(0x0b, 0x20);
if(~inb(0x20)&0x80) {
spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
return -1;
}
}
spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
return irq;
}
static void i8259_mask_and_ack_irq(unsigned int irq_nr)
{
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
if ( irq_nr >= i8259_pic_irq_offset )
irq_nr -= i8259_pic_irq_offset;
if (irq_nr > 7) {
cached_A1 |= 1 << (irq_nr-8);
inb(0xA1); /* DUMMY */
outb(cached_A1,0xA1);
outb(0x20,0xA0); /* Non-specific EOI */
outb(0x20,0x20); /* Non-specific EOI to cascade */
} else {
cached_21 |= 1 << irq_nr;
inb(0x21); /* DUMMY */
outb(cached_21,0x21);
outb(0x20,0x20); /* Non-specific EOI */
}
spin_unlock_irqrestore(&i8259_lock, flags);
}
static void i8259_set_irq_mask(int irq_nr)
{
outb(cached_A1,0xA1);
outb(cached_21,0x21);
}
static void i8259_mask_irq(unsigned int irq_nr)
{
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
if ( irq_nr >= i8259_pic_irq_offset )
irq_nr -= i8259_pic_irq_offset;
if ( irq_nr < 8 )
cached_21 |= 1 << irq_nr;
else
cached_A1 |= 1 << (irq_nr-8);
i8259_set_irq_mask(irq_nr);
spin_unlock_irqrestore(&i8259_lock, flags);
}
static void i8259_unmask_irq(unsigned int irq_nr)
{
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
if ( irq_nr >= i8259_pic_irq_offset )
irq_nr -= i8259_pic_irq_offset;
if ( irq_nr < 8 )
cached_21 &= ~(1 << irq_nr);
else
cached_A1 &= ~(1 << (irq_nr-8));
i8259_set_irq_mask(irq_nr);
spin_unlock_irqrestore(&i8259_lock, flags);
}
static void i8259_end_irq(unsigned int irq)
{
if (!(get_irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
get_irq_desc(irq)->action)
i8259_unmask_irq(irq);
}
struct hw_interrupt_type i8259_pic = {
.typename = " i8259 ",
.enable = i8259_unmask_irq,
.disable = i8259_mask_irq,
.ack = i8259_mask_and_ack_irq,
.end = i8259_end_irq,
};
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 */
outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
outb(0x01, 0x21); /* Select 8086 mode */
outb(0xFF, 0x21); /* Mask all */
/* init slave interrupt controller */
outb(0x11, 0xA0); /* Start init sequence */
outb(0x08, 0xA1); /* Vector base */
outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
outb(0x01, 0xA1); /* Select 8086 mode */
outb(0xFF, 0xA1); /* Mask all */
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);
......@@ -5,7 +5,8 @@
extern struct hw_interrupt_type i8259_pic;
extern void i8259_init(long intack_addr);
extern void i8259_init(unsigned long intack_addr, int offset);
extern int i8259_irq(struct pt_regs *regs);
extern int i8259_irq_cascade(struct pt_regs *regs, void *unused);
#endif /* _ASM_POWERPC_I8259_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