1
2
3
4
5
6
7
8
9#include <linux/timex.h>
10#include <linux/time.h>
11#include <linux/jiffies.h>
12#include <linux/interrupt.h>
13#include <linux/swap.h>
14#include <linux/sched.h>
15#include <linux/init.h>
16#include <linux/mm.h>
17#include <asm/types.h>
18#include <asm/signal.h>
19#include <asm/io.h>
20#include <asm/delay.h>
21#include <asm/irq_regs.h>
22
23
24
25#undef USE_CASCADE_TIMERS
26
27unsigned long get_ns_in_jiffie(void)
28{
29 unsigned char timer_count, t1;
30 unsigned short presc_count;
31 unsigned long ns;
32 unsigned long flags;
33
34 local_irq_save(flags);
35 timer_count = *R_TIMER0_DATA;
36 presc_count = *R_TIM_PRESC_STATUS;
37
38 t1 = *R_TIMER0_DATA;
39
40 if (timer_count != t1){
41
42 presc_count = *R_TIM_PRESC_STATUS;
43 timer_count = t1;
44 }
45 local_irq_restore(flags);
46 if (presc_count >= PRESCALE_VALUE/2 ){
47 presc_count = PRESCALE_VALUE - presc_count + PRESCALE_VALUE/2;
48 } else {
49 presc_count = PRESCALE_VALUE - presc_count - PRESCALE_VALUE/2;
50 }
51
52 ns = ( (TIMER0_DIV - timer_count) * ((1000000000/HZ)/TIMER0_DIV )) +
53 ( (presc_count) * (1000000000/PRESCALE_FREQ));
54 return ns;
55}
56
57static u32 cris_v10_gettimeoffset(void)
58{
59 u32 count;
60
61
62
63
64
65 count = *R_TIMER0_DATA;
66
67
68 return (TIMER0_DIV - count) * (NSEC_PER_SEC/HZ)/TIMER0_DIV;
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#define start_watchdog reset_watchdog
98
99#ifdef CONFIG_ETRAX_WATCHDOG
100static int watchdog_key = 0;
101#endif
102
103
104
105
106
107#define WATCHDOG_MIN_FREE_PAGES 8
108
109void reset_watchdog(void)
110{
111#if defined(CONFIG_ETRAX_WATCHDOG)
112
113 if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) {
114
115 watchdog_key ^= 0x7;
116 *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) |
117 IO_STATE(R_WATCHDOG, enable, start);
118 }
119#endif
120}
121
122
123
124void stop_watchdog(void)
125{
126#ifdef CONFIG_ETRAX_WATCHDOG
127 watchdog_key ^= 0x7;
128 *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) |
129 IO_STATE(R_WATCHDOG, enable, stop);
130#endif
131}
132
133
134extern void cris_do_profile(struct pt_regs *regs);
135
136
137
138
139
140static inline irqreturn_t timer_interrupt(int irq, void *dev_id)
141{
142 struct pt_regs *regs = get_irq_regs();
143
144
145#ifdef USE_CASCADE_TIMERS
146 *R_TIMER_CTRL =
147 IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
148 IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
149 IO_STATE( R_TIMER_CTRL, i1, clr) |
150 IO_STATE( R_TIMER_CTRL, tm1, run) |
151 IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
152 IO_STATE( R_TIMER_CTRL, i0, clr) |
153 IO_STATE( R_TIMER_CTRL, tm0, run) |
154 IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
155#else
156 *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i0, clr);
157#endif
158
159
160 reset_watchdog();
161
162
163 update_process_times(user_mode(regs));
164
165
166 xtime_update(1);
167
168 cris_do_profile(regs);
169 return IRQ_HANDLED;
170}
171
172
173
174static struct irqaction irq2 = {
175 .handler = timer_interrupt,
176 .flags = IRQF_SHARED,
177 .name = "timer",
178};
179
180void __init time_init(void)
181{
182 arch_gettimeoffset = cris_v10_gettimeoffset;
183
184
185
186
187
188
189
190 loops_per_usec = 50;
191
192
193
194
195
196
197
198
199
200#ifdef USE_CASCADE_TIMERS
201 *R_TIMER_CTRL =
202 IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
203 IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
204 IO_STATE( R_TIMER_CTRL, i1, nop) |
205 IO_STATE( R_TIMER_CTRL, tm1, stop_ld) |
206 IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
207 IO_STATE( R_TIMER_CTRL, i0, nop) |
208 IO_STATE( R_TIMER_CTRL, tm0, stop_ld) |
209 IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
210
211 *R_TIMER_CTRL = r_timer_ctrl_shadow =
212 IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
213 IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
214 IO_STATE( R_TIMER_CTRL, i1, nop) |
215 IO_STATE( R_TIMER_CTRL, tm1, run) |
216 IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
217 IO_STATE( R_TIMER_CTRL, i0, nop) |
218 IO_STATE( R_TIMER_CTRL, tm0, run) |
219 IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
220#else
221 *R_TIMER_CTRL =
222 IO_FIELD(R_TIMER_CTRL, timerdiv1, 192) |
223 IO_FIELD(R_TIMER_CTRL, timerdiv0, TIMER0_DIV) |
224 IO_STATE(R_TIMER_CTRL, i1, nop) |
225 IO_STATE(R_TIMER_CTRL, tm1, stop_ld) |
226 IO_STATE(R_TIMER_CTRL, clksel1, c19k2Hz) |
227 IO_STATE(R_TIMER_CTRL, i0, nop) |
228 IO_STATE(R_TIMER_CTRL, tm0, stop_ld) |
229 IO_STATE(R_TIMER_CTRL, clksel0, flexible);
230
231 *R_TIMER_CTRL = r_timer_ctrl_shadow =
232 IO_FIELD(R_TIMER_CTRL, timerdiv1, 192) |
233 IO_FIELD(R_TIMER_CTRL, timerdiv0, TIMER0_DIV) |
234 IO_STATE(R_TIMER_CTRL, i1, nop) |
235 IO_STATE(R_TIMER_CTRL, tm1, run) |
236 IO_STATE(R_TIMER_CTRL, clksel1, c19k2Hz) |
237 IO_STATE(R_TIMER_CTRL, i0, nop) |
238 IO_STATE(R_TIMER_CTRL, tm0, run) |
239 IO_STATE(R_TIMER_CTRL, clksel0, flexible);
240
241 *R_TIMER_PRESCALE = PRESCALE_VALUE;
242#endif
243
244
245 *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer0, set);
246
247
248 setup_irq(2, &irq2);
249
250
251#if defined(CONFIG_ETRAX_WATCHDOG)
252 printk("Enabling watchdog...\n");
253 start_watchdog();
254
255
256
257
258
259
260
261
262 asm ("setf m");
263
264 *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, watchdog_nmi, set);
265 *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, nmi, set);
266#endif
267}
268