blob: f6031707aeb1805f7f7ad5e253a5bc910b27e660 [file] [log] [blame]
wdenka8c7c702003-12-06 19:49:23 +00001/*
2 * (C) Copyright 2000-2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * (C) Copyright 2003
6 * Gleb Natapov <gnatapov@mrv.com>
7 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 */
26
27#include <common.h>
28#include <asm/processor.h>
29#include <watchdog.h>
30#ifdef CONFIG_STATUS_LED
31#include <status_led.h>
32#endif
33
34#ifdef CONFIG_SHOW_ACTIVITY
Wolfgang Denkaab2bf02008-09-09 10:08:02 +020035void board_show_activity (ulong) __attribute__((weak, alias("__board_show_activity")));
36
37void __board_show_activity (ulong dummy)
38{
39 return;
40}
wdenka8c7c702003-12-06 19:49:23 +000041#endif /* CONFIG_SHOW_ACTIVITY */
42
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020043#ifndef CONFIG_SYS_WATCHDOG_FREQ
44#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
wdenka8c7c702003-12-06 19:49:23 +000045#endif
46
47extern int interrupt_init_cpu (unsigned *);
48extern void timer_interrupt_cpu (struct pt_regs *);
49
50static unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
51
52static __inline__ unsigned long get_msr (void)
53{
wdenkd4ca31c2004-01-02 14:00:00 +000054 unsigned long msr;
wdenka8c7c702003-12-06 19:49:23 +000055
wdenkd4ca31c2004-01-02 14:00:00 +000056 asm volatile ("mfmsr %0":"=r" (msr):);
wdenka8c7c702003-12-06 19:49:23 +000057
wdenkd4ca31c2004-01-02 14:00:00 +000058 return msr;
wdenka8c7c702003-12-06 19:49:23 +000059}
60
61static __inline__ void set_msr (unsigned long msr)
62{
63 asm volatile ("mtmsr %0"::"r" (msr));
64}
65
66static __inline__ unsigned long get_dec (void)
67{
68 unsigned long val;
69
70 asm volatile ("mfdec %0":"=r" (val):);
71
72 return val;
73}
74
75
76static __inline__ void set_dec (unsigned long val)
77{
78 if (val)
79 asm volatile ("mtdec %0"::"r" (val));
80}
81
82
83void enable_interrupts (void)
84{
85 set_msr (get_msr () | MSR_EE);
86}
87
88/* returns flag if MSR_EE was set before */
89int disable_interrupts (void)
90{
91 ulong msr = get_msr ();
92
93 set_msr (msr & ~MSR_EE);
94 return ((msr & MSR_EE) != 0);
95}
96
97int interrupt_init (void)
98{
99 int ret;
100
wdenkd4ca31c2004-01-02 14:00:00 +0000101 /* call cpu specific function from $(CPU)/interrupts.c */
wdenka8c7c702003-12-06 19:49:23 +0000102 ret = interrupt_init_cpu (&decrementer_count);
103
104 if (ret)
105 return ret;
106
107 set_dec (decrementer_count);
108
109 set_msr (get_msr () | MSR_EE);
110
111 return (0);
112}
113
114static volatile ulong timestamp = 0;
115
116void timer_interrupt (struct pt_regs *regs)
117{
118 /* call cpu specific function from $(CPU)/interrupts.c */
119 timer_interrupt_cpu (regs);
120
121 /* Restore Decrementer Count */
122 set_dec (decrementer_count);
123
124 timestamp++;
125
126#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200127 if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
wdenka8c7c702003-12-06 19:49:23 +0000128 WATCHDOG_RESET ();
129#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
130
131#ifdef CONFIG_STATUS_LED
wdenkd4ca31c2004-01-02 14:00:00 +0000132 status_led_tick (timestamp);
wdenka8c7c702003-12-06 19:49:23 +0000133#endif /* CONFIG_STATUS_LED */
134
135#ifdef CONFIG_SHOW_ACTIVITY
136 board_show_activity (timestamp);
137#endif /* CONFIG_SHOW_ACTIVITY */
138}
139
140void reset_timer (void)
141{
142 timestamp = 0;
143}
144
145ulong get_timer (ulong base)
146{
147 return (timestamp - base);
148}
149
150void set_timer (ulong t)
151{
152 timestamp = t;
153}