1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2000-2002
3*4882a593Smuzhiyun * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
6*4882a593Smuzhiyun * Scott McNutt <smcnutt@psyent.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <command.h>
13*4882a593Smuzhiyun #include <asm/nios2.h>
14*4882a593Smuzhiyun #include <asm/types.h>
15*4882a593Smuzhiyun #include <asm/io.h>
16*4882a593Smuzhiyun #include <asm/ptrace.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun /*************************************************************************/
19*4882a593Smuzhiyun struct irq_action {
20*4882a593Smuzhiyun interrupt_handler_t *handler;
21*4882a593Smuzhiyun void *arg;
22*4882a593Smuzhiyun int count;
23*4882a593Smuzhiyun };
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun static struct irq_action vecs[32];
26*4882a593Smuzhiyun
disable_interrupts(void)27*4882a593Smuzhiyun int disable_interrupts (void)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun int val = rdctl (CTL_STATUS);
30*4882a593Smuzhiyun wrctl (CTL_STATUS, val & ~STATUS_IE);
31*4882a593Smuzhiyun return (val & STATUS_IE);
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun
enable_interrupts(void)34*4882a593Smuzhiyun void enable_interrupts( void )
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun int val = rdctl (CTL_STATUS);
37*4882a593Smuzhiyun wrctl (CTL_STATUS, val | STATUS_IE);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun
external_interrupt(struct pt_regs * regs)40*4882a593Smuzhiyun void external_interrupt (struct pt_regs *regs)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun unsigned irqs;
43*4882a593Smuzhiyun struct irq_action *act;
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /* Evaluate only irqs that are both enabled AND pending */
46*4882a593Smuzhiyun irqs = rdctl (CTL_IENABLE) & rdctl (CTL_IPENDING);
47*4882a593Smuzhiyun act = vecs;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /* Assume (as does the Nios2 HAL) that bit 0 is highest
50*4882a593Smuzhiyun * priority. NOTE: There is ALWAYS a handler assigned
51*4882a593Smuzhiyun * (the default if no other).
52*4882a593Smuzhiyun */
53*4882a593Smuzhiyun while (irqs) {
54*4882a593Smuzhiyun if (irqs & 1) {
55*4882a593Smuzhiyun act->handler (act->arg);
56*4882a593Smuzhiyun act->count++;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun irqs >>=1;
59*4882a593Smuzhiyun act++;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
def_hdlr(void * arg)63*4882a593Smuzhiyun static void def_hdlr (void *arg)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun unsigned irqs = rdctl (CTL_IENABLE);
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /* Disable the individual interrupt -- with gratuitous
68*4882a593Smuzhiyun * warning.
69*4882a593Smuzhiyun */
70*4882a593Smuzhiyun irqs &= ~(1 << (int)arg);
71*4882a593Smuzhiyun wrctl (CTL_IENABLE, irqs);
72*4882a593Smuzhiyun printf ("WARNING: Disabling unhandled interrupt: %d\n",
73*4882a593Smuzhiyun (int)arg);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /*************************************************************************/
irq_install_handler(int irq,interrupt_handler_t * hdlr,void * arg)77*4882a593Smuzhiyun void irq_install_handler (int irq, interrupt_handler_t *hdlr, void *arg)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun int flag;
81*4882a593Smuzhiyun struct irq_action *act;
82*4882a593Smuzhiyun unsigned ena = rdctl (CTL_IENABLE);
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun if ((irq < 0) || (irq > 31))
85*4882a593Smuzhiyun return;
86*4882a593Smuzhiyun act = &vecs[irq];
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun flag = disable_interrupts ();
89*4882a593Smuzhiyun if (hdlr) {
90*4882a593Smuzhiyun act->handler = hdlr;
91*4882a593Smuzhiyun act->arg = arg;
92*4882a593Smuzhiyun ena |= (1 << irq); /* enable */
93*4882a593Smuzhiyun } else {
94*4882a593Smuzhiyun act->handler = def_hdlr;
95*4882a593Smuzhiyun act->arg = (void *)irq;
96*4882a593Smuzhiyun ena &= ~(1 << irq); /* disable */
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun wrctl (CTL_IENABLE, ena);
99*4882a593Smuzhiyun if (flag) enable_interrupts ();
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun
interrupt_init(void)103*4882a593Smuzhiyun int interrupt_init (void)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun int i;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* Assign the default handler to all */
108*4882a593Smuzhiyun for (i = 0; i < 32; i++) {
109*4882a593Smuzhiyun vecs[i].handler = def_hdlr;
110*4882a593Smuzhiyun vecs[i].arg = (void *)i;
111*4882a593Smuzhiyun vecs[i].count = 0;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun enable_interrupts ();
115*4882a593Smuzhiyun return (0);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /*************************************************************************/
120*4882a593Smuzhiyun #if defined(CONFIG_CMD_IRQ)
do_irqinfo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])121*4882a593Smuzhiyun int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun int i;
124*4882a593Smuzhiyun struct irq_action *act = vecs;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun printf ("\nInterrupt-Information:\n\n");
127*4882a593Smuzhiyun printf ("Nr Routine Arg Count\n");
128*4882a593Smuzhiyun printf ("-----------------------------\n");
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun for (i=0; i<32; i++) {
131*4882a593Smuzhiyun if (act->handler != def_hdlr) {
132*4882a593Smuzhiyun printf ("%02d %08lx %08lx %d\n",
133*4882a593Smuzhiyun i,
134*4882a593Smuzhiyun (ulong)act->handler,
135*4882a593Smuzhiyun (ulong)act->arg,
136*4882a593Smuzhiyun act->count);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun act++;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun printf ("\n");
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun return (0);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun #endif
145