aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/sun3/sun3ints.c
blob: 626b601931e948df266a9a92c6f8f3a2ffafbb05 (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
140
 /*
 * linux/arch/m68k/sun3/sun3ints.c -- Sun-3(x) Linux interrupt handling code
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive
 * for more details.
 */

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
#include <asm/segment.h>
#include <asm/intersil.h>
#include <asm/oplib.h>
#include <asm/sun3ints.h>
#include <asm/irq_regs.h>
#include <linux/seq_file.h>

extern void sun3_leds (unsigned char);

void sun3_disable_interrupts(void)
{
	sun3_disable_irq(0);
}

void sun3_enable_interrupts(void)
{
	sun3_enable_irq(0);
}

static int led_pattern[8] = {
       ~(0x80), ~(0x01),
       ~(0x40), ~(0x02),
       ~(0x20), ~(0x04),
       ~(0x10), ~(0x08)
};

volatile unsigned char* sun3_intreg;

void sun3_enable_irq(unsigned int irq)
{
	*sun3_intreg |=  (1 << irq);
}

void sun3_disable_irq(unsigned int irq)
{
	*sun3_intreg &= ~(1 << irq);
}

static irqreturn_t sun3_int7(int irq, void *dev_id)
{
	unsigned int cnt;

#ifndef CONFIG_GENERIC_HARDIRQS
	*sun3_intreg |=  (1 << irq);
#endif
	cnt = kstat_irqs_cpu(irq, 0);
	if (!(cnt % 2000))
		sun3_leds(led_pattern[cnt % 16000 / 2000]);
	return IRQ_HANDLED;
}

static irqreturn_t sun3_int5(int irq, void *dev_id)
{
	unsigned int cnt;

#ifdef CONFIG_SUN3
	intersil_clear();
#endif
#ifndef CONFIG_GENERIC_HARDIRQS
        *sun3_intreg |=  (1 << irq);
#endif
#ifdef CONFIG_SUN3
	intersil_clear();
#endif
	xtime_update(1);
	update_process_times(user_mode(get_irq_regs()));
	cnt = kstat_irqs_cpu(irq, 0);
	if (!(cnt % 20))
		sun3_leds(led_pattern[cnt % 160 / 20]);
	return IRQ_HANDLED;
}

static irqreturn_t sun3_vec255(int irq, void *dev_id)
{
//	intersil_clear();
	return IRQ_HANDLED;
}

#ifndef CONFIG_GENERIC_HARDIRQS
static void sun3_inthandle(unsigned int irq, struct pt_regs *fp)
{
        *sun3_intreg &= ~(1 << irq);

	do_IRQ(irq, fp);
}
#endif

static void sun3_irq_enable(struct irq_data *data)
{
    sun3_enable_irq(data->irq);
};

static void sun3_irq_disable(struct irq_data *data)
{
    sun3_disable_irq(data->irq);
};

static struct irq_chip sun3_irq_chip = {
	.name		= "sun3",
	.irq_startup	= m68k_irq_startup,
	.irq_shutdown	= m68k_irq_shutdown,
	.irq_enable	= sun3_irq_enable,
	.irq_disable	= sun3_irq_disable,
#ifdef CONFIG_GENERIC_HARDIRQS
	.irq_mask	= sun3_irq_disable,
	.irq_unmask	= sun3_irq_enable,
#endif
};

void __init sun3_init_IRQ(void)
{
	*sun3_intreg = 1;

#ifndef CONFIG_GENERIC_HARDIRQS
	m68k_setup_auto_interrupt(sun3_inthandle);
#endif
	m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1,
				  7);
	m68k_setup_user_interrupt(VEC_USER, 128, NULL);

	if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
		pr_err("Couldn't register %s interrupt\n", "int5");
	if (request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL))
		pr_err("Couldn't register %s interrupt\n", "int7");
	if (request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL))
		pr_err("Couldn't register %s interrupt\n", "vec255");
}