#include <linux/sched.h>
|
#include <linux/sched.h>
|
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
|
|
#include <asm/io.h>
|
#include <asm/io.h>
|
#include <asm/system.h>
|
#include <asm/system.h>
|
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
#include <asm/irq.h>
|
#include <asm/irq.h>
|
#include <asm/arch/irq.h>
|
#include <asm/arch/irq.h>
|
|
|
|
|
|
|
/* The trio AIC need to recive EOI command at the end of interrupt handler,
|
/* The trio AIC need to recive EOI command at the end of interrupt handler,
|
These command is compossed from previous IRQ nr and previous IRQ priority.
|
These command is compossed from previous IRQ nr and previous IRQ priority.
|
So we maintain this value in the trio_irq_prority variable.
|
So we maintain this value in the trio_irq_prority variable.
|
|
|
The trio_irq_prtable contains the priority<<5 for each IRQ
|
The trio_irq_prtable contains the priority<<5 for each IRQ
|
*/
|
*/
|
|
|
volatile unsigned char trio_irq_priority = 0; /* Current IRQ number and priority */
|
volatile unsigned char trio_irq_priority = 0; /* Current IRQ number and priority */
|
unsigned char trio_irq_prtable[16] = {
|
unsigned char trio_irq_prtable[16] = {
|
7, /* FIQ */
|
7, /* FIQ */
|
0, /* WDIRQ */
|
0, /* WDIRQ */
|
0, /* SWIRQ */
|
0, /* SWIRQ */
|
2, /* UAIRQ */
|
2, /* UAIRQ */
|
0, /* TC0 (Timer 0 used for DRAM refresh */
|
0, /* TC0 (Timer 0 used for DRAM refresh */
|
1, /* TC1IRQ */
|
1, /* TC1IRQ */
|
0, /* TC2IRQ */
|
0, /* TC2IRQ */
|
0, /* PIOAIRQ */
|
0, /* PIOAIRQ */
|
0, /* LCDIRQ not used */
|
0, /* LCDIRQ not used */
|
5, /* SPIIRQ */
|
5, /* SPIIRQ */
|
4, /* IRQ0, (ETHERNET? )*/
|
4, /* IRQ0, (ETHERNET? )*/
|
0, /* IRQ1 */
|
0, /* IRQ1 */
|
6, /* OAKAIRQ */
|
6, /* OAKAIRQ */
|
6, /* OAKBIRQ */
|
6, /* OAKBIRQ */
|
3, /* UBIRQ */
|
3, /* UBIRQ */
|
5 /* PIOBIRQ */
|
5 /* PIOBIRQ */
|
|
|
};
|
};
|
|
|
void do_IRQ(int irq, struct pt_regs * regs);
|
void do_IRQ(int irq, struct pt_regs * regs);
|
|
|
|
|
inline void irq_ack(int priority)
|
inline void irq_ack(int priority)
|
{
|
{
|
outl(priority, AIC_EOICR);
|
outl(priority, AIC_EOICR);
|
}
|
}
|
|
|
asmlinkage int probe_IRQ_interrupt(int irq, struct pt_regs * regs)
|
asmlinkage int probe_IRQ_interrupt(int irq, struct pt_regs * regs)
|
{
|
{
|
mask_irq(irq);
|
mask_irq(irq);
|
irq_ack(trio_irq_priority);
|
irq_ack(trio_irq_priority);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
asmlinkage int bad_IRQ_interrupt(int irqn, struct pt_regs * regs)
|
asmlinkage int bad_IRQ_interrupt(int irqn, struct pt_regs * regs)
|
{
|
{
|
printk("bad interrupt %d recieved!\n", irqn);
|
printk("bad interrupt %d recieved!\n", irqn);
|
irq_ack(trio_irq_priority);
|
irq_ack(trio_irq_priority);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
asmlinkage int IRQ_interrupt(int irq, struct pt_regs * regs)
|
asmlinkage int IRQ_interrupt(int irq, struct pt_regs * regs)
|
{
|
{
|
register unsigned long flags;
|
register unsigned long flags;
|
register unsigned long saved_count;
|
register unsigned long saved_count;
|
register unsigned char spr = trio_irq_priority;
|
register unsigned char spr = trio_irq_priority;
|
|
|
trio_irq_priority = ((unsigned char)irq) | trio_irq_prtable[irq];
|
trio_irq_priority = ((unsigned char)irq) | trio_irq_prtable[irq];
|
|
|
|
|
saved_count = intr_count;
|
saved_count = intr_count;
|
intr_count = saved_count + 1;
|
intr_count = saved_count + 1;
|
|
|
save_flags(flags);
|
save_flags(flags);
|
sti();
|
sti();
|
do_IRQ(irq, regs);
|
do_IRQ(irq, regs);
|
restore_flags(flags);
|
restore_flags(flags);
|
intr_count = saved_count;
|
intr_count = saved_count;
|
trio_irq_priority = spr;
|
trio_irq_priority = spr;
|
irq_ack(spr);
|
irq_ack(spr);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
asmlinkage int timer_IRQ_interrupt(int irq, struct pt_regs * regs)
|
asmlinkage int timer_IRQ_interrupt(int irq, struct pt_regs * regs)
|
{
|
{
|
register unsigned long flags;
|
register unsigned long flags;
|
register unsigned long saved_count;
|
register unsigned long saved_count;
|
register unsigned char spr = trio_irq_priority;
|
register unsigned char spr = trio_irq_priority;
|
|
|
trio_irq_priority = ((unsigned char)irq) | trio_irq_prtable[irq];
|
trio_irq_priority = ((unsigned char)irq) | trio_irq_prtable[irq];
|
|
|
|
|
|
|
saved_count = intr_count;
|
saved_count = intr_count;
|
intr_count = saved_count + 1;
|
intr_count = saved_count + 1;
|
|
|
save_flags(flags);
|
save_flags(flags);
|
do_IRQ(irq, regs);
|
do_IRQ(irq, regs);
|
restore_flags(flags);
|
restore_flags(flags);
|
intr_count = saved_count;
|
intr_count = saved_count;
|
trio_irq_priority = spr;
|
trio_irq_priority = spr;
|
irq_ack(spr);
|
irq_ack(spr);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
asmlinkage int fast_IRQ_interrupt(int irq, struct pt_regs * regs)
|
asmlinkage int fast_IRQ_interrupt(int irq, struct pt_regs * regs)
|
{
|
{
|
register unsigned long saved_count;
|
register unsigned long saved_count;
|
|
|
saved_count = intr_count;
|
saved_count = intr_count;
|
intr_count = saved_count + 1;
|
intr_count = saved_count + 1;
|
|
|
do_IRQ(irq, regs);
|
do_IRQ(irq, regs);
|
cli();
|
cli();
|
intr_count = saved_count;
|
intr_count = saved_count;
|
inl(AIC_FVR);
|
inl(AIC_FVR);
|
return 1;
|
return 1;
|
}
|
}
|
|
|
void trio_init_aic()
|
void trio_init_aic()
|
{
|
{
|
int irqno;
|
int irqno;
|
|
|
// Disable all interrupts
|
// Disable all interrupts
|
outl(0xFFFFFFFF, AIC_IDCR);
|
outl(0xFFFFFFFF, AIC_IDCR);
|
|
|
// Clear all interrupts
|
// Clear all interrupts
|
outl(0xFFFFFFFF, AIC_ICCR);
|
outl(0xFFFFFFFF, AIC_ICCR);
|
|
|
for ( irqno = 0 ; irqno < 8 ; irqno++ )
|
for ( irqno = 0 ; irqno < 8 ; irqno++ )
|
{
|
{
|
outl(irqno, AIC_EOICR);
|
outl(irqno, AIC_EOICR);
|
}
|
}
|
|
|
|
|
|
|
for ( irqno = 0 ; irqno < 16 ; irqno++ )
|
for ( irqno = 0 ; irqno < 16 ; irqno++ )
|
{
|
{
|
outl(trio_irq_prtable[irqno] | (1 << 5), AIC_SMR(irqno));
|
outl(trio_irq_prtable[irqno] | (1 << 5), AIC_SMR(irqno));
|
}
|
}
|
}
|
}
|
|
|