2 * (C) Copyright 2000-2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
6 * Scott McNutt <smcnutt@psyent.com>
8 * SPDX-License-Identifier: GPL-2.0+
12 #include <asm/nios2.h>
13 #include <asm/types.h>
15 #include <asm/ptrace.h>
19 #ifdef CONFIG_STATUS_LED
20 #include <status_led.h>
23 typedef volatile struct {
24 unsigned status; /* Timer status reg */
25 unsigned control; /* Timer control reg */
26 unsigned periodl; /* Timeout period low */
27 unsigned periodh; /* Timeout period high */
28 unsigned snapl; /* Snapshot low */
29 unsigned snaph; /* Snapshot high */
33 #define NIOS_TIMER_TO (1 << 0) /* Timeout */
34 #define NIOS_TIMER_RUN (1 << 1) /* Timer running */
36 /* control register */
37 #define NIOS_TIMER_ITO (1 << 0) /* Timeout int ena */
38 #define NIOS_TIMER_CONT (1 << 1) /* Continuous mode */
39 #define NIOS_TIMER_START (1 << 2) /* Start timer */
40 #define NIOS_TIMER_STOP (1 << 3) /* Stop timer */
42 #if defined(CONFIG_SYS_NIOS_TMRBASE) && !defined(CONFIG_SYS_NIOS_TMRIRQ)
43 #error CONFIG_SYS_NIOS_TMRIRQ not defined (see documentation)
46 /****************************************************************************/
49 interrupt_handler_t *handler;
54 static struct irq_action vecs[32];
56 /*************************************************************************/
57 volatile ulong timestamp = 0;
59 void reset_timer (void)
61 nios_timer_t *tmr =(nios_timer_t *)CONFIG_SYS_NIOS_TMRBASE;
63 /* From Embedded Peripherals Handbook:
65 * "When the hardware is configured with Writeable period
66 * disabled, writing to one of the period_n registers causes
67 * the counter to reset to the fixed Timeout Period specified
68 * at system generation time."
70 * Here we force a reload to prevent early timeouts from
71 * get_timer() when the interrupt period is greater than
74 * Simply write to periodl with its own value to force an
75 * internal counter reload, THEN reset the timestamp.
77 writel (readl (&tmr->periodl), &tmr->periodl);
80 /* From Embedded Peripherals Handbook:
82 * "Writing to one of the period_n registers stops the internal
83 * counter, except when the hardware is configured with Start/Stop
84 * control bits off. If Start/Stop control bits is off, writing
85 * either register does not stop the counter."
87 * In order to accomodate either configuration, the control
88 * register is re-written. If the counter is stopped, it will
89 * be restarted. If it is running, the write is essentially
92 writel (NIOS_TIMER_ITO | NIOS_TIMER_CONT | NIOS_TIMER_START,
97 ulong get_timer (ulong base)
100 return (timestamp - base);
104 * This function is derived from Blackfin code (read timebase as long long).
105 * On Nios2 it just returns the timer value.
107 unsigned long long get_ticks(void)
113 * This function is derived from Blackfin code.
114 * On Nios2 it returns the number of timer ticks per second.
116 ulong get_tbclk(void)
120 tbclk = CONFIG_SYS_HZ;
124 /* The board must handle this interrupt if a timer is not
127 #if defined(CONFIG_SYS_NIOS_TMRBASE)
128 void tmr_isr (void *arg)
130 nios_timer_t *tmr = (nios_timer_t *)arg;
131 /* Interrupt is cleared by writing anything to the
134 writel (0, &tmr->status);
135 timestamp += CONFIG_SYS_NIOS_TMRMS;
136 #ifdef CONFIG_STATUS_LED
137 status_led_tick(timestamp);
141 static void tmr_init (void)
143 nios_timer_t *tmr =(nios_timer_t *)CONFIG_SYS_NIOS_TMRBASE;
145 writel (0, &tmr->status);
146 writel (0, &tmr->control);
147 writel (NIOS_TIMER_STOP, &tmr->control);
149 #if defined(CONFIG_SYS_NIOS_TMRCNT)
150 writel (CONFIG_SYS_NIOS_TMRCNT & 0xffff, &tmr->periodl);
151 writel ((CONFIG_SYS_NIOS_TMRCNT >> 16) & 0xffff, &tmr->periodh);
153 writel (NIOS_TIMER_ITO | NIOS_TIMER_CONT | NIOS_TIMER_START,
155 irq_install_handler (CONFIG_SYS_NIOS_TMRIRQ, tmr_isr, (void *)tmr);
158 #endif /* CONFIG_SYS_NIOS_TMRBASE */
160 /*************************************************************************/
161 int disable_interrupts (void)
163 int val = rdctl (CTL_STATUS);
164 wrctl (CTL_STATUS, val & ~STATUS_IE);
165 return (val & STATUS_IE);
168 void enable_interrupts( void )
170 int val = rdctl (CTL_STATUS);
171 wrctl (CTL_STATUS, val | STATUS_IE);
174 void external_interrupt (struct pt_regs *regs)
177 struct irq_action *act;
179 /* Evaluate only irqs that are both enabled AND pending */
180 irqs = rdctl (CTL_IENABLE) & rdctl (CTL_IPENDING);
183 /* Assume (as does the Nios2 HAL) that bit 0 is highest
184 * priority. NOTE: There is ALWAYS a handler assigned
185 * (the default if no other).
189 act->handler (act->arg);
197 static void def_hdlr (void *arg)
199 unsigned irqs = rdctl (CTL_IENABLE);
201 /* Disable the individual interrupt -- with gratuitous
204 irqs &= ~(1 << (int)arg);
205 wrctl (CTL_IENABLE, irqs);
206 printf ("WARNING: Disabling unhandled interrupt: %d\n",
210 /*************************************************************************/
211 void irq_install_handler (int irq, interrupt_handler_t *hdlr, void *arg)
215 struct irq_action *act;
216 unsigned ena = rdctl (CTL_IENABLE);
218 if ((irq < 0) || (irq > 31))
222 flag = disable_interrupts ();
226 ena |= (1 << irq); /* enable */
228 act->handler = def_hdlr;
229 act->arg = (void *)irq;
230 ena &= ~(1 << irq); /* disable */
232 wrctl (CTL_IENABLE, ena);
233 if (flag) enable_interrupts ();
237 int interrupt_init (void)
241 /* Assign the default handler to all */
242 for (i = 0; i < 32; i++) {
243 vecs[i].handler = def_hdlr;
244 vecs[i].arg = (void *)i;
248 #if defined(CONFIG_SYS_NIOS_TMRBASE)
252 enable_interrupts ();
257 /*************************************************************************/
258 #if defined(CONFIG_CMD_IRQ)
259 int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
262 struct irq_action *act = vecs;
264 printf ("\nInterrupt-Information:\n\n");
265 printf ("Nr Routine Arg Count\n");
266 printf ("-----------------------------\n");
268 for (i=0; i<32; i++) {
269 if (act->handler != def_hdlr) {
270 printf ("%02d %08lx %08lx %d\n",