forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[MIPS] Atlas: update interrupt handling
The following change updates the Atlas interrupt handling to match that of Malta. Tested with a 5Kc and a 34Kf successfully. Signed-off-by: Maciej W. Rozycki <[email protected]> Signed-off-by: Ralf Baechle <[email protected]>
- Loading branch information
1 parent
3ee24e1
commit fc095a9
Showing
6 changed files
with
189 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
/* | ||
* Carsten Langgaard, [email protected] | ||
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. | ||
* Copyright (C) 1999, 2000, 2006 MIPS Technologies, Inc. | ||
* All rights reserved. | ||
* Authors: Carsten Langgaard <[email protected]> | ||
* Maciej W. Rozycki <[email protected]> | ||
* | ||
* ######################################################################## | ||
* | ||
|
@@ -25,17 +27,20 @@ | |
*/ | ||
#include <linux/compiler.h> | ||
#include <linux/init.h> | ||
#include <linux/irq.h> | ||
#include <linux/sched.h> | ||
#include <linux/slab.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/kernel_stat.h> | ||
|
||
#include <asm/irq.h> | ||
#include <asm/gdb-stub.h> | ||
#include <asm/io.h> | ||
#include <asm/irq_cpu.h> | ||
#include <asm/msc01_ic.h> | ||
|
||
#include <asm/mips-boards/atlas.h> | ||
#include <asm/mips-boards/atlasint.h> | ||
#include <asm/gdb-stub.h> | ||
|
||
#include <asm/mips-boards/generic.h> | ||
|
||
static struct atlas_ictrl_regs *atlas_hw0_icregs; | ||
|
||
|
@@ -47,13 +52,13 @@ static struct atlas_ictrl_regs *atlas_hw0_icregs; | |
|
||
void disable_atlas_irq(unsigned int irq_nr) | ||
{ | ||
atlas_hw0_icregs->intrsten = (1 << (irq_nr-ATLASINT_BASE)); | ||
atlas_hw0_icregs->intrsten = 1 << (irq_nr - ATLAS_INT_BASE); | ||
iob(); | ||
} | ||
|
||
void enable_atlas_irq(unsigned int irq_nr) | ||
{ | ||
atlas_hw0_icregs->intseten = (1 << (irq_nr-ATLASINT_BASE)); | ||
atlas_hw0_icregs->intseten = 1 << (irq_nr - ATLAS_INT_BASE); | ||
iob(); | ||
} | ||
|
||
|
@@ -107,7 +112,7 @@ static inline void atlas_hw0_irqdispatch(struct pt_regs *regs) | |
if (unlikely(int_status == 0)) | ||
return; | ||
|
||
irq = ATLASINT_BASE + ls1bit32(int_status); | ||
irq = ATLAS_INT_BASE + ls1bit32(int_status); | ||
|
||
DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq); | ||
|
||
|
@@ -161,15 +166,14 @@ static inline unsigned int irq_ffs(unsigned int pending) | |
} | ||
|
||
/* | ||
* IRQs on the Atlas board look basically (barring software IRQs which we | ||
* don't use at all and all external interrupt sources are combined together | ||
* on hardware interrupt 0 (MIPS IRQ 2)) like: | ||
* IRQs on the Atlas board look basically like (all external interrupt | ||
* sources are combined together on hardware interrupt 0 (MIPS IRQ 2)): | ||
* | ||
* MIPS IRQ Source | ||
* MIPS IRQ Source | ||
* -------- ------ | ||
* 0 Software (ignored) | ||
* 1 Software (ignored) | ||
* 2 Combined hardware interrupt (hw0) | ||
* 0 Software 0 (reschedule IPI on MT) | ||
* 1 Software 1 (remote call IPI on MT) | ||
* 2 Combined Atlas hardware interrupt (hw0) | ||
* 3 Hardware (ignored) | ||
* 4 Hardware (ignored) | ||
* 5 Hardware (ignored) | ||
|
@@ -179,7 +183,7 @@ static inline unsigned int irq_ffs(unsigned int pending) | |
* We handle the IRQ according to _our_ priority which is: | ||
* | ||
* Highest ---- R4k Timer | ||
* Lowest ---- Combined hardware interrupt | ||
* Lowest ---- Software 0 | ||
* | ||
* then we just return, if multiple IRQs are pending then we will just take | ||
* another exception, big deal. | ||
|
@@ -193,29 +197,90 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs) | |
|
||
if (irq == MIPSCPU_INT_ATLAS) | ||
atlas_hw0_irqdispatch(regs); | ||
else if (irq > 0) | ||
else if (irq >= 0) | ||
do_IRQ(MIPSCPU_INT_BASE + irq, regs); | ||
else | ||
spurious_interrupt(regs); | ||
} | ||
|
||
void __init arch_init_irq(void) | ||
static inline void init_atlas_irqs (int base) | ||
{ | ||
int i; | ||
|
||
atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *)); | ||
atlas_hw0_icregs = (struct atlas_ictrl_regs *) | ||
ioremap(ATLAS_ICTRL_REGS_BASE, | ||
sizeof(struct atlas_ictrl_regs *)); | ||
|
||
/* | ||
* Mask out all interrupt by writing "1" to all bit position in | ||
* the interrupt reset reg. | ||
*/ | ||
atlas_hw0_icregs->intrsten = 0xffffffff; | ||
|
||
for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) { | ||
for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) { | ||
irq_desc[i].status = IRQ_DISABLED; | ||
irq_desc[i].action = 0; | ||
irq_desc[i].depth = 1; | ||
irq_desc[i].chip = &atlas_irq_type; | ||
spin_lock_init(&irq_desc[i].lock); | ||
} | ||
} | ||
|
||
static struct irqaction atlasirq = { | ||
.handler = no_action, | ||
.name = "Atlas cascade" | ||
}; | ||
|
||
msc_irqmap_t __initdata msc_irqmap[] = { | ||
{MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, | ||
{MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, | ||
}; | ||
int __initdata msc_nr_irqs = sizeof(msc_irqmap) / sizeof(*msc_irqmap); | ||
|
||
msc_irqmap_t __initdata msc_eicirqmap[] = { | ||
{MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, | ||
{MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0}, | ||
{MSC01E_INT_ATLAS, MSC01_IRQ_LEVEL, 0}, | ||
{MSC01E_INT_TMR, MSC01_IRQ_EDGE, 0}, | ||
{MSC01E_INT_PCI, MSC01_IRQ_LEVEL, 0}, | ||
{MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0}, | ||
{MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} | ||
}; | ||
int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap) / sizeof(*msc_eicirqmap); | ||
|
||
void __init arch_init_irq(void) | ||
{ | ||
init_atlas_irqs(ATLAS_INT_BASE); | ||
|
||
if (!cpu_has_veic) | ||
mips_cpu_irq_init(MIPSCPU_INT_BASE); | ||
|
||
switch(mips_revision_corid) { | ||
case MIPS_REVISION_CORID_CORE_MSC: | ||
case MIPS_REVISION_CORID_CORE_FPGA2: | ||
case MIPS_REVISION_CORID_CORE_FPGA3: | ||
case MIPS_REVISION_CORID_CORE_24K: | ||
case MIPS_REVISION_CORID_CORE_EMUL_MSC: | ||
if (cpu_has_veic) | ||
init_msc_irqs (MSC01E_INT_BASE, | ||
msc_eicirqmap, msc_nr_eicirqs); | ||
else | ||
init_msc_irqs (MSC01C_INT_BASE, | ||
msc_irqmap, msc_nr_irqs); | ||
} | ||
|
||
|
||
if (cpu_has_veic) { | ||
set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch); | ||
setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq); | ||
} else if (cpu_has_vint) { | ||
set_vi_handler (MIPSCPU_INT_ATLAS, atlas_hw0_irqdispatch); | ||
#ifdef CONFIG_MIPS_MT_SMTC | ||
setup_irq_smtc (MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, | ||
&atlasirq, (0x100 << MIPSCPU_INT_ATLAS)); | ||
#else /* Not SMTC */ | ||
setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq); | ||
#endif /* CONFIG_MIPS_MT_SMTC */ | ||
} else | ||
setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
/* | ||
* Carsten Langgaard, [email protected] | ||
* Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved. | ||
* Copyright (C) 1999, 2006 MIPS Technologies, Inc. All rights reserved. | ||
* Authors: Carsten Langgaard <[email protected]> | ||
* Maciej W. Rozycki <[email protected]> | ||
* | ||
* ######################################################################## | ||
* | ||
|
@@ -25,41 +26,88 @@ | |
#ifndef _MIPS_ATLASINT_H | ||
#define _MIPS_ATLASINT_H | ||
|
||
#define ATLASINT_BASE 1 | ||
#define ATLASINT_UART (ATLASINT_BASE+0) | ||
#define ATLASINT_TIM0 (ATLASINT_BASE+1) | ||
#define ATLASINT_RES2 (ATLASINT_BASE+2) | ||
#define ATLASINT_RES3 (ATLASINT_BASE+3) | ||
#define ATLASINT_RTC (ATLASINT_BASE+4) | ||
#define ATLASINT_COREHI (ATLASINT_BASE+5) | ||
#define ATLASINT_CORELO (ATLASINT_BASE+6) | ||
#define ATLASINT_RES7 (ATLASINT_BASE+7) | ||
#define ATLASINT_PCIA (ATLASINT_BASE+8) | ||
#define ATLASINT_PCIB (ATLASINT_BASE+9) | ||
#define ATLASINT_PCIC (ATLASINT_BASE+10) | ||
#define ATLASINT_PCID (ATLASINT_BASE+11) | ||
#define ATLASINT_ENUM (ATLASINT_BASE+12) | ||
#define ATLASINT_DEG (ATLASINT_BASE+13) | ||
#define ATLASINT_ATXFAIL (ATLASINT_BASE+14) | ||
#define ATLASINT_INTA (ATLASINT_BASE+15) | ||
#define ATLASINT_INTB (ATLASINT_BASE+16) | ||
#define ATLASINT_ETH ATLASINT_INTB | ||
#define ATLASINT_INTC (ATLASINT_BASE+17) | ||
#define ATLASINT_SCSI ATLASINT_INTC | ||
#define ATLASINT_INTD (ATLASINT_BASE+18) | ||
#define ATLASINT_SERR (ATLASINT_BASE+19) | ||
#define ATLASINT_RES20 (ATLASINT_BASE+20) | ||
#define ATLASINT_RES21 (ATLASINT_BASE+21) | ||
#define ATLASINT_RES22 (ATLASINT_BASE+22) | ||
#define ATLASINT_RES23 (ATLASINT_BASE+23) | ||
#define ATLASINT_RES24 (ATLASINT_BASE+24) | ||
#define ATLASINT_RES25 (ATLASINT_BASE+25) | ||
#define ATLASINT_RES26 (ATLASINT_BASE+26) | ||
#define ATLASINT_RES27 (ATLASINT_BASE+27) | ||
#define ATLASINT_RES28 (ATLASINT_BASE+28) | ||
#define ATLASINT_RES29 (ATLASINT_BASE+29) | ||
#define ATLASINT_RES30 (ATLASINT_BASE+30) | ||
#define ATLASINT_RES31 (ATLASINT_BASE+31) | ||
#define ATLASINT_END (ATLASINT_BASE+31) | ||
/* | ||
* Interrupts 0..7 are used for Atlas CPU interrupts (nonEIC mode) | ||
*/ | ||
#define MIPSCPU_INT_BASE 0 | ||
|
||
/* CPU interrupt offsets */ | ||
#define MIPSCPU_INT_SW0 0 | ||
#define MIPSCPU_INT_SW1 1 | ||
#define MIPSCPU_INT_MB0 2 | ||
#define MIPSCPU_INT_ATLAS MIPSCPU_INT_MB0 | ||
#define MIPSCPU_INT_MB1 3 | ||
#define MIPSCPU_INT_MB2 4 | ||
#define MIPSCPU_INT_MB3 5 | ||
#define MIPSCPU_INT_MB4 6 | ||
#define MIPSCPU_INT_CPUCTR 7 | ||
|
||
/* | ||
* Interrupts 8..39 are used for Atlas interrupt controller interrupts | ||
*/ | ||
#define ATLAS_INT_BASE 8 | ||
#define ATLAS_INT_UART (ATLAS_INT_BASE + 0) | ||
#define ATLAS_INT_TIM0 (ATLAS_INT_BASE + 1) | ||
#define ATLAS_INT_RES2 (ATLAS_INT_BASE + 2) | ||
#define ATLAS_INT_RES3 (ATLAS_INT_BASE + 3) | ||
#define ATLAS_INT_RTC (ATLAS_INT_BASE + 4) | ||
#define ATLAS_INT_COREHI (ATLAS_INT_BASE + 5) | ||
#define ATLAS_INT_CORELO (ATLAS_INT_BASE + 6) | ||
#define ATLAS_INT_RES7 (ATLAS_INT_BASE + 7) | ||
#define ATLAS_INT_PCIA (ATLAS_INT_BASE + 8) | ||
#define ATLAS_INT_PCIB (ATLAS_INT_BASE + 9) | ||
#define ATLAS_INT_PCIC (ATLAS_INT_BASE + 10) | ||
#define ATLAS_INT_PCID (ATLAS_INT_BASE + 11) | ||
#define ATLAS_INT_ENUM (ATLAS_INT_BASE + 12) | ||
#define ATLAS_INT_DEG (ATLAS_INT_BASE + 13) | ||
#define ATLAS_INT_ATXFAIL (ATLAS_INT_BASE + 14) | ||
#define ATLAS_INT_INTA (ATLAS_INT_BASE + 15) | ||
#define ATLAS_INT_INTB (ATLAS_INT_BASE + 16) | ||
#define ATLAS_INT_ETH ATLAS_INT_INTB | ||
#define ATLAS_INT_INTC (ATLAS_INT_BASE + 17) | ||
#define ATLAS_INT_SCSI ATLAS_INT_INTC | ||
#define ATLAS_INT_INTD (ATLAS_INT_BASE + 18) | ||
#define ATLAS_INT_SERR (ATLAS_INT_BASE + 19) | ||
#define ATLAS_INT_RES20 (ATLAS_INT_BASE + 20) | ||
#define ATLAS_INT_RES21 (ATLAS_INT_BASE + 21) | ||
#define ATLAS_INT_RES22 (ATLAS_INT_BASE + 22) | ||
#define ATLAS_INT_RES23 (ATLAS_INT_BASE + 23) | ||
#define ATLAS_INT_RES24 (ATLAS_INT_BASE + 24) | ||
#define ATLAS_INT_RES25 (ATLAS_INT_BASE + 25) | ||
#define ATLAS_INT_RES26 (ATLAS_INT_BASE + 26) | ||
#define ATLAS_INT_RES27 (ATLAS_INT_BASE + 27) | ||
#define ATLAS_INT_RES28 (ATLAS_INT_BASE + 28) | ||
#define ATLAS_INT_RES29 (ATLAS_INT_BASE + 29) | ||
#define ATLAS_INT_RES30 (ATLAS_INT_BASE + 30) | ||
#define ATLAS_INT_RES31 (ATLAS_INT_BASE + 31) | ||
#define ATLAS_INT_END (ATLAS_INT_BASE + 31) | ||
|
||
/* | ||
* Interrupts 64..127 are used for Soc-it Classic interrupts | ||
*/ | ||
#define MSC01C_INT_BASE 64 | ||
|
||
/* SOC-it Classic interrupt offsets */ | ||
#define MSC01C_INT_TMR 0 | ||
#define MSC01C_INT_PCI 1 | ||
|
||
/* | ||
* Interrupts 64..127 are used for Soc-it EIC interrupts | ||
*/ | ||
#define MSC01E_INT_BASE 64 | ||
|
||
/* SOC-it EIC interrupt offsets */ | ||
#define MSC01E_INT_SW0 1 | ||
#define MSC01E_INT_SW1 2 | ||
#define MSC01E_INT_MB0 3 | ||
#define MSC01E_INT_ATLAS MSC01E_INT_MB0 | ||
#define MSC01E_INT_MB1 4 | ||
#define MSC01E_INT_MB2 5 | ||
#define MSC01E_INT_MB3 6 | ||
#define MSC01E_INT_MB4 7 | ||
#define MSC01E_INT_TMR 8 | ||
#define MSC01E_INT_PCI 9 | ||
#define MSC01E_INT_PERFCTR 10 | ||
#define MSC01E_INT_CPUCTR 11 | ||
|
||
#endif /* !(_MIPS_ATLASINT_H) */ |