summaryrefslogtreecommitdiffstats
path: root/arch/mips/cobalt/via.c
blob: 7ab5e1e69d869cf7816fe2e9f40bafba4f61a5cd (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
/*
 * Interrupt handling for the VIA ISA bridge.
 *
 * Everything the same ... just different ...
 */
#include <linux/kernel.h>
#include <asm/cobalt.h>
#include <asm/ptrace.h>
#include <asm/io.h>

extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs);

extern unsigned char cache_21;
extern unsigned char cache_A1;

/*
 * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
 * PCI devices.  Other onboard hardware needs specific routines.
 */
void mask_irq(unsigned int irq_nr)
{
	unsigned char mask;

	mask = 1 << (irq_nr & 7);
	if (irq_nr < 8) {
		cache_21 |= mask;
		outb(cache_21, 0x10000021);
	} else {
		cache_A1 |= mask;
		outb(cache_A1, 0x100000a1);
	}
}

void unmask_irq(unsigned int irq_nr)
{
	unsigned char mask;

	mask = ~(1 << (irq_nr & 7));
	if (irq_nr < 8) {
		cache_21 &= mask;
		outb(cache_21, 0x10000021);
	} else {
		cache_A1 &= mask;
		outb(cache_A1, 0x100000a1);
	}
}

asmlinkage void via_irq(struct pt_regs *regs)
{
	char mstat, sstat;
  
	/* Read Master Status */
	VIA_PORT_WRITE(0x20, 0x0C);
	mstat = VIA_PORT_READ(0x20);
 
	if (mstat < 0) {
		mstat &= 0x7f;
		if (mstat != 2) {     	
			do_IRQ(mstat, regs);
			VIA_PORT_WRITE(0x20, mstat | 0x20);
		} else {
			sstat = VIA_PORT_READ(0xA0);

			/* Slave interrupt */
			VIA_PORT_WRITE(0xA0, 0x0C);
			sstat = VIA_PORT_READ(0xA0);
   
			if (sstat < 0) {
				do_IRQ((sstat + 8) & 0x7f, regs);
				VIA_PORT_WRITE(0x20, 0x22);       
				VIA_PORT_WRITE(0xA0, (sstat & 0x7f) | 0x20);
			} else {
				printk("Spurious slave interrupt...\n");
			}
		}
	} else
		printk("Spurious master interrupt...");
}

asmlinkage void galileo_irq(struct pt_regs *regs)
{
	unsigned long irq_src = *((unsigned long *) 0xb4000c18); 
  
	/* Check for timer irq ... */
	if (irq_src & 0x00000100) {
		*((volatile unsigned long *) 0xb4000c18) = 0;
		do_IRQ(0, regs);
	} else
		printk("Spurious Galileo interrupt...\n");
}