summaryrefslogtreecommitdiffstats
path: root/include/asm-arm/arch-ebsa285/irq.h
blob: 74bc33c58e466277b1b825c739f9dc30db1ecba9 (plain)
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
131
132
133
134
135
136
137
138
139
/*
 * include/asm-arm/arch-ebsa285/irq.h
 *
 * Copyright (C) 1996-1998 Russell King
 *
 * Changelog:
 *   22-08-1998	RMK	Restructured IRQ routines
 *   03-09-1998	PJB	Merged CATS support
 */
#include <linux/config.h>

static void ebsa285_mask_irq(unsigned int irq)
{
	*CSR_IRQ_DISABLE = 1 << irq;
}

static void ebsa285_unmask_irq(unsigned int irq)
{
	*CSR_IRQ_ENABLE = 1 << irq;
}

#ifdef CONFIG_CATS

/*
 * This contains the irq mask for both 8259A irq controllers,
 */
static unsigned int isa_irq_mask = 0xffff;

#define cached_21	(isa_irq_mask & 0xff)
#define cached_A1	((isa_irq_mask >> 8) & 0xff)

#define update_8259(_irq)			\
	if ((_irq) & 8)				\
		outb(cached_A1, 0xa1);		\
	else					\
		outb(cached_21, 0x21);

static void isa_interrupt(int irq, void *h, struct pt_regs *regs)
{
	asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
	unsigned int irqbits = inb(0x20) | (inb(0xa0) << 8), irqnr = 0;
	irqbits &= ~(1<<2);	/* don't try to service the cascade */
	while (irqbits) {
		if (irqbits & 1)
			do_IRQ(32 + irqnr, regs);
		irqbits >>= 1;
		irqnr++;
	}
}

static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }

static struct irqaction irq_isa = 
		{ isa_interrupt, SA_INTERRUPT, 0, "ISA PIC", NULL, NULL };
static struct irqaction irq_cascade = 
		{ no_action, 0, 0, "cascade", NULL, NULL };

static void cats_mask_and_ack_isa_irq(unsigned int irq)
{
	isa_irq_mask |= (1 << (irq - 32));
	update_8259(irq);
	if (irq & 8) {
		inb(0xA1);	/* DUMMY */
		outb(cached_A1,0xA1);
		outb(0x62,0x20);	/* Specific EOI to cascade */
		outb(0x20,0xA0);
	} else {
		inb(0x21);	/* DUMMY */
		outb(cached_21,0x21);
		outb(0x20,0x20);
	}
}

static void cats_mask_isa_irq(unsigned int irq)
{
	isa_irq_mask |= (1 << (irq - 32));
	update_8259(irq);
}

static void cats_unmask_isa_irq(unsigned int irq)
{
	isa_irq_mask &= ~(1 << (irq - 32));
	update_8259(irq);
}
 
#endif 

static __inline__ void irq_init_irq(void)
{
	int irq;

	*CSR_IRQ_DISABLE = -1;
	*CSR_FIQ_DISABLE = -1;

	for (irq = 0; irq < NR_IRQS; irq++) {
		irq_desc[irq].valid	= 1;
		irq_desc[irq].probe_ok	= 1;
#ifdef CONFIG_CATS
		if (machine_is_cats() && IRQ_IS_ISA(irq)) {
			irq_desc[irq].mask_ack	= cats_mask_and_ack_isa_irq;
			irq_desc[irq].mask	= cats_mask_isa_irq;
			irq_desc[irq].unmask	= cats_unmask_isa_irq;
		} else
#endif
		{
			irq_desc[irq].mask_ack	= ebsa285_mask_irq;
			irq_desc[irq].mask	= ebsa285_mask_irq;
			irq_desc[irq].unmask	= ebsa285_unmask_irq;
		}
	}

#ifdef CONFIG_CATS
	if (machine_is_cats()) {
		request_region(0x20, 2, "pic1");
		request_region(0xa0, 2, "pic2");

		/* set up master 8259 */
		outb(0x11, 0x20);
		outb(0, 0x21);
		outb(1<<2, 0x21);
		outb(0x1, 0x21);
		outb(0xff, 0x21);
		outb(0x68, 0x20);
		outb(0xa, 0x20);
		
		/* set up slave 8259 */
		outb(0x11, 0xa0);
		outb(0, 0xa1);
		outb(2, 0xa1);
		outb(0x1, 0xa1);
		outb(0xff, 0xa1);
		outb(0x68, 0xa0);
		outb(0xa, 0xa0);

		setup_arm_irq(IRQ_ISA_PIC, &irq_isa);
		setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade);
	}
#endif
}