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+
14
#include <asm/types.h>
16
#include <asm/ptrace.h>
20
#ifdef CONFIG_STATUS_LED
21
#include <status_led.h>
24
#if defined(CONFIG_SYS_NIOS_TMRBASE) && !defined(CONFIG_SYS_NIOS_TMRIRQ)
25
#error CONFIG_SYS_NIOS_TMRIRQ not defined (see documentation)
28
/****************************************************************************/
31
interrupt_handler_t *handler;
36
static struct irq_action vecs[32];
38
/*************************************************************************/
39
volatile ulong timestamp = 0;
41
void reset_timer (void)
43
nios_timer_t *tmr =(nios_timer_t *)CONFIG_SYS_NIOS_TMRBASE;
45
/* From Embedded Peripherals Handbook:
47
* "When the hardware is configured with Writeable period
48
* disabled, writing to one of the period_n registers causes
49
* the counter to reset to the fixed Timeout Period specified
50
* at system generation time."
52
* Here we force a reload to prevent early timeouts from
53
* get_timer() when the interrupt period is greater than
56
* Simply write to periodl with its own value to force an
57
* internal counter reload, THEN reset the timestamp.
59
writel (readl (&tmr->periodl), &tmr->periodl);
62
/* From Embedded Peripherals Handbook:
64
* "Writing to one of the period_n registers stops the internal
65
* counter, except when the hardware is configured with Start/Stop
66
* control bits off. If Start/Stop control bits is off, writing
67
* either register does not stop the counter."
69
* In order to accomodate either configuration, the control
70
* register is re-written. If the counter is stopped, it will
71
* be restarted. If it is running, the write is essentially
74
writel (NIOS_TIMER_ITO | NIOS_TIMER_CONT | NIOS_TIMER_START,
79
ulong get_timer (ulong base)
82
return (timestamp - base);
86
* This function is derived from Blackfin code (read timebase as long long).
87
* On Nios2 it just returns the timer value.
89
unsigned long long get_ticks(void)
95
* This function is derived from Blackfin code.
96
* On Nios2 it returns the number of timer ticks per second.
102
tbclk = CONFIG_SYS_HZ;
106
/* The board must handle this interrupt if a timer is not
109
#if defined(CONFIG_SYS_NIOS_TMRBASE)
110
void tmr_isr (void *arg)
112
nios_timer_t *tmr = (nios_timer_t *)arg;
113
/* Interrupt is cleared by writing anything to the
116
writel (0, &tmr->status);
117
timestamp += CONFIG_SYS_NIOS_TMRMS;
118
#ifdef CONFIG_STATUS_LED
119
status_led_tick(timestamp);
123
static void tmr_init (void)
125
nios_timer_t *tmr =(nios_timer_t *)CONFIG_SYS_NIOS_TMRBASE;
127
writel (0, &tmr->status);
128
writel (0, &tmr->control);
129
writel (NIOS_TIMER_STOP, &tmr->control);
131
#if defined(CONFIG_SYS_NIOS_TMRCNT)
132
writel (CONFIG_SYS_NIOS_TMRCNT & 0xffff, &tmr->periodl);
133
writel ((CONFIG_SYS_NIOS_TMRCNT >> 16) & 0xffff, &tmr->periodh);
135
writel (NIOS_TIMER_ITO | NIOS_TIMER_CONT | NIOS_TIMER_START,
137
irq_install_handler (CONFIG_SYS_NIOS_TMRIRQ, tmr_isr, (void *)tmr);
140
#endif /* CONFIG_SYS_NIOS_TMRBASE */
142
/*************************************************************************/
143
int disable_interrupts (void)
145
int val = rdctl (CTL_STATUS);
146
wrctl (CTL_STATUS, val & ~STATUS_IE);
147
return (val & STATUS_IE);
150
void enable_interrupts( void )
152
int val = rdctl (CTL_STATUS);
153
wrctl (CTL_STATUS, val | STATUS_IE);
156
void external_interrupt (struct pt_regs *regs)
159
struct irq_action *act;
161
/* Evaluate only irqs that are both enabled AND pending */
162
irqs = rdctl (CTL_IENABLE) & rdctl (CTL_IPENDING);
165
/* Assume (as does the Nios2 HAL) that bit 0 is highest
166
* priority. NOTE: There is ALWAYS a handler assigned
167
* (the default if no other).
171
act->handler (act->arg);
179
static void def_hdlr (void *arg)
181
unsigned irqs = rdctl (CTL_IENABLE);
183
/* Disable the individual interrupt -- with gratuitous
186
irqs &= ~(1 << (int)arg);
187
wrctl (CTL_IENABLE, irqs);
188
printf ("WARNING: Disabling unhandled interrupt: %d\n",
192
/*************************************************************************/
193
void irq_install_handler (int irq, interrupt_handler_t *hdlr, void *arg)
197
struct irq_action *act;
198
unsigned ena = rdctl (CTL_IENABLE);
200
if ((irq < 0) || (irq > 31))
204
flag = disable_interrupts ();
208
ena |= (1 << irq); /* enable */
210
act->handler = def_hdlr;
211
act->arg = (void *)irq;
212
ena &= ~(1 << irq); /* disable */
214
wrctl (CTL_IENABLE, ena);
215
if (flag) enable_interrupts ();
219
int interrupt_init (void)
223
/* Assign the default handler to all */
224
for (i = 0; i < 32; i++) {
225
vecs[i].handler = def_hdlr;
226
vecs[i].arg = (void *)i;
230
#if defined(CONFIG_SYS_NIOS_TMRBASE)
234
enable_interrupts ();
239
/*************************************************************************/
240
#if defined(CONFIG_CMD_IRQ)
241
int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
244
struct irq_action *act = vecs;
246
printf ("\nInterrupt-Information:\n\n");
247
printf ("Nr Routine Arg Count\n");
248
printf ("-----------------------------\n");
250
for (i=0; i<32; i++) {
251
if (act->handler != def_hdlr) {
252
printf ("%02d %08lx %08lx %d\n",