Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | /*
* arch/ppc/platforms/adir_pic.c
*
* Interrupt controller support for SBS Adirondack
*
* By Michael Sokolov <msokolov@ivan.Harhan.ORG>
* based on the K2 and SCM versions by Matt Porter <mporter@mvista.com>
*/
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/i8259.h>
#include "adir.h"
static void adir_onboard_pic_enable(unsigned int irq);
static void adir_onboard_pic_disable(unsigned int irq);
__init static void
adir_onboard_pic_init(void)
{
volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
/* Disable all Adirondack onboard interrupts */
out_be16(maskreg, 0xFFFF);
}
static int
adir_onboard_pic_get_irq(void)
{
volatile u_short *statreg = (volatile u_short *) ADIR_PROCA_INT_STAT;
int irq;
u_short int_status, int_test;
int_status = in_be16(statreg);
for (irq = 0, int_test = 1; irq < 16; irq++, int_test <<= 1) {
if (int_status & int_test)
break;
}
if (irq == 16)
return -1;
return (irq+16);
}
static void
adir_onboard_pic_enable(unsigned int irq)
{
volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
/* Change irq to Adirondack onboard native value */
irq -= 16;
/* Enable requested irq number */
out_be16(maskreg, in_be16(maskreg) & ~(1 << irq));
}
static void
adir_onboard_pic_disable(unsigned int irq)
{
volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
/* Change irq to Adirondack onboard native value */
irq -= 16;
/* Disable requested irq number */
out_be16(maskreg, in_be16(maskreg) | (1 << irq));
}
static struct hw_interrupt_type adir_onboard_pic = {
" ADIR PIC ",
NULL,
NULL,
adir_onboard_pic_enable, /* unmask */
adir_onboard_pic_disable, /* mask */
adir_onboard_pic_disable, /* mask and ack */
NULL,
NULL
};
static struct irqaction noop_action = {
.handler = no_action,
.flags = SA_INTERRUPT,
.mask = CPU_MASK_NONE,
.name = "82c59 primary cascade",
};
/*
* Linux interrupt values are assigned as follows:
*
* 0-15 VT82C686 8259 interrupts
* 16-31 Adirondack CPLD interrupts
*/
__init void
adir_init_IRQ(void)
{
int i;
/* Initialize the cascaded 8259's on the VT82C686 */
for (i=0; i<16; i++)
irq_desc[i].handler = &i8259_pic;
i8259_init(NULL);
/* Initialize Adirondack CPLD PIC and enable 8259 interrupt cascade */
for (i=16; i<32; i++)
irq_desc[i].handler = &adir_onboard_pic;
adir_onboard_pic_init();
/* Enable 8259 interrupt cascade */
setup_irq(ADIR_IRQ_VT82C686_INTR, &noop_action);
}
int
adir_get_irq(struct pt_regs *regs)
{
int irq;
if ((irq = adir_onboard_pic_get_irq()) < 0)
return irq;
if (irq == ADIR_IRQ_VT82C686_INTR)
irq = i8259_irq(regs);
return irq;
}
|