Merge branch 'qemu-cvs'
[qemu-kvm/fedora.git] / hw / etraxfs_timer.c
blobe996c57f6a4cb016108ae85186620673be193c8b
1 /*
2 * QEMU ETRAX Timers
4 * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
24 #include <stdio.h>
25 #include <sys/time.h>
26 #include "hw.h"
27 #include "sysemu.h"
28 #include "qemu-timer.h"
30 #define D(x)
32 #define RW_TMR0_DIV 0x00
33 #define R_TMR0_DATA 0x04
34 #define RW_TMR0_CTRL 0x08
35 #define RW_TMR1_DIV 0x10
36 #define R_TMR1_DATA 0x14
37 #define RW_TMR1_CTRL 0x18
38 #define R_TIME 0x38
39 #define RW_WD_CTRL 0x40
40 #define R_WD_STAT 0x44
41 #define RW_INTR_MASK 0x48
42 #define RW_ACK_INTR 0x4c
43 #define R_INTR 0x50
44 #define R_MASKED_INTR 0x54
46 struct fs_timer_t {
47 CPUState *env;
48 qemu_irq *irq;
49 qemu_irq *nmi;
50 target_phys_addr_t base;
52 QEMUBH *bh_t0;
53 QEMUBH *bh_t1;
54 QEMUBH *bh_wd;
55 ptimer_state *ptimer_t0;
56 ptimer_state *ptimer_t1;
57 ptimer_state *ptimer_wd;
58 struct timeval last;
60 int wd_hits;
62 /* Control registers. */
63 uint32_t rw_tmr0_div;
64 uint32_t r_tmr0_data;
65 uint32_t rw_tmr0_ctrl;
67 uint32_t rw_tmr1_div;
68 uint32_t r_tmr1_data;
69 uint32_t rw_tmr1_ctrl;
71 uint32_t rw_wd_ctrl;
73 uint32_t rw_intr_mask;
74 uint32_t rw_ack_intr;
75 uint32_t r_intr;
76 uint32_t r_masked_intr;
79 static uint32_t timer_rinvalid (void *opaque, target_phys_addr_t addr)
81 struct fs_timer_t *t = opaque;
82 CPUState *env = t->env;
83 cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n",
84 addr, env->pc);
85 return 0;
88 static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
90 struct fs_timer_t *t = opaque;
91 D(CPUState *env = t->env);
92 uint32_t r = 0;
94 /* Make addr relative to this instances base. */
95 addr -= t->base;
96 switch (addr) {
97 case R_TMR0_DATA:
98 break;
99 case R_TMR1_DATA:
100 D(printf ("R_TMR1_DATA\n"));
101 break;
102 case R_TIME:
103 r = qemu_get_clock(vm_clock) * 10;
104 break;
105 case RW_INTR_MASK:
106 r = t->rw_intr_mask;
107 break;
108 case R_MASKED_INTR:
109 r = t->r_intr & t->rw_intr_mask;
110 break;
111 default:
112 D(printf ("%s %x p=%x\n", __func__, addr, env->pc));
113 break;
115 return r;
118 static void
119 timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value)
121 struct fs_timer_t *t = opaque;
122 CPUState *env = t->env;
123 cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n",
124 addr, env->pc);
127 #define TIMER_SLOWDOWN 1
128 static void update_ctrl(struct fs_timer_t *t, int tnum)
130 unsigned int op;
131 unsigned int freq;
132 unsigned int freq_hz;
133 unsigned int div;
134 uint32_t ctrl;
136 ptimer_state *timer;
138 if (tnum == 0) {
139 ctrl = t->rw_tmr0_ctrl;
140 div = t->rw_tmr0_div;
141 timer = t->ptimer_t0;
142 } else {
143 ctrl = t->rw_tmr1_ctrl;
144 div = t->rw_tmr1_div;
145 timer = t->ptimer_t1;
149 op = ctrl & 3;
150 freq = ctrl >> 2;
151 freq_hz = 32000000;
153 switch (freq)
155 case 0:
156 case 1:
157 D(printf ("extern or disabled timer clock?\n"));
158 break;
159 case 4: freq_hz = 29493000; break;
160 case 5: freq_hz = 32000000; break;
161 case 6: freq_hz = 32768000; break;
162 case 7: freq_hz = 100001000; break;
163 default:
164 abort();
165 break;
168 D(printf ("freq_hz=%d div=%d\n", freq_hz, div));
169 div = div * TIMER_SLOWDOWN;
170 div >>= 10;
171 freq_hz >>= 10;
172 ptimer_set_freq(timer, freq_hz);
173 ptimer_set_limit(timer, div, 0);
175 switch (op)
177 case 0:
178 /* Load. */
179 ptimer_set_limit(timer, div, 1);
180 break;
181 case 1:
182 /* Hold. */
183 ptimer_stop(timer);
184 break;
185 case 2:
186 /* Run. */
187 ptimer_run(timer, 0);
188 break;
189 default:
190 abort();
191 break;
195 static void timer_update_irq(struct fs_timer_t *t)
197 t->r_intr &= ~(t->rw_ack_intr);
198 t->r_masked_intr = t->r_intr & t->rw_intr_mask;
200 D(printf("%s: masked_intr=%x\n", __func__, t->r_masked_intr));
201 if (t->r_masked_intr)
202 qemu_irq_raise(t->irq[0]);
203 else
204 qemu_irq_lower(t->irq[0]);
207 static void timer0_hit(void *opaque)
209 struct fs_timer_t *t = opaque;
210 t->r_intr |= 1;
211 timer_update_irq(t);
214 static void timer1_hit(void *opaque)
216 struct fs_timer_t *t = opaque;
217 t->r_intr |= 2;
218 timer_update_irq(t);
221 static void watchdog_hit(void *opaque)
223 struct fs_timer_t *t = opaque;
224 if (t->wd_hits == 0) {
225 /* real hw gives a single tick before reseting but we are
226 a bit friendlier to compensate for our slower execution. */
227 ptimer_set_count(t->ptimer_wd, 10);
228 ptimer_run(t->ptimer_wd, 1);
229 qemu_irq_raise(t->nmi[0]);
231 else
232 qemu_system_reset_request();
234 t->wd_hits++;
237 static inline void timer_watchdog_update(struct fs_timer_t *t, uint32_t value)
239 unsigned int wd_en = t->rw_wd_ctrl & (1 << 8);
240 unsigned int wd_key = t->rw_wd_ctrl >> 9;
241 unsigned int wd_cnt = t->rw_wd_ctrl & 511;
242 unsigned int new_key = value >> 9 & ((1 << 7) - 1);
243 unsigned int new_cmd = (value >> 8) & 1;
245 /* If the watchdog is enabled, they written key must match the
246 complement of the previous. */
247 wd_key = ~wd_key & ((1 << 7) - 1);
249 if (wd_en && wd_key != new_key)
250 return;
252 D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n",
253 wd_en, new_key, wd_key, new_cmd, wd_cnt));
255 if (t->wd_hits)
256 qemu_irq_lower(t->nmi[0]);
258 t->wd_hits = 0;
260 ptimer_set_freq(t->ptimer_wd, 760);
261 if (wd_cnt == 0)
262 wd_cnt = 256;
263 ptimer_set_count(t->ptimer_wd, wd_cnt);
264 if (new_cmd)
265 ptimer_run(t->ptimer_wd, 1);
266 else
267 ptimer_stop(t->ptimer_wd);
269 t->rw_wd_ctrl = value;
272 static void
273 timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
275 struct fs_timer_t *t = opaque;
276 CPUState *env = t->env;
278 /* Make addr relative to this instances base. */
279 addr -= t->base;
280 switch (addr)
282 case RW_TMR0_DIV:
283 t->rw_tmr0_div = value;
284 break;
285 case RW_TMR0_CTRL:
286 D(printf ("RW_TMR0_CTRL=%x\n", value));
287 t->rw_tmr0_ctrl = value;
288 update_ctrl(t, 0);
289 break;
290 case RW_TMR1_DIV:
291 t->rw_tmr1_div = value;
292 break;
293 case RW_TMR1_CTRL:
294 D(printf ("RW_TMR1_CTRL=%x\n", value));
295 t->rw_tmr1_ctrl = value;
296 update_ctrl(t, 1);
297 break;
298 case RW_INTR_MASK:
299 D(printf ("RW_INTR_MASK=%x\n", value));
300 t->rw_intr_mask = value;
301 timer_update_irq(t);
302 break;
303 case RW_WD_CTRL:
304 timer_watchdog_update(t, value);
305 break;
306 case RW_ACK_INTR:
307 t->rw_ack_intr = value;
308 timer_update_irq(t);
309 t->rw_ack_intr = 0;
310 break;
311 default:
312 printf ("%s %x %x pc=%x\n",
313 __func__, addr, value, env->pc);
314 break;
318 static CPUReadMemoryFunc *timer_read[] = {
319 &timer_rinvalid,
320 &timer_rinvalid,
321 &timer_readl,
324 static CPUWriteMemoryFunc *timer_write[] = {
325 &timer_winvalid,
326 &timer_winvalid,
327 &timer_writel,
330 static void etraxfs_timer_reset(void *opaque)
332 struct fs_timer_t *t = opaque;
334 ptimer_stop(t->ptimer_t0);
335 ptimer_stop(t->ptimer_t1);
336 ptimer_stop(t->ptimer_wd);
337 t->rw_wd_ctrl = 0;
338 t->r_intr = 0;
339 t->rw_intr_mask = 0;
340 qemu_irq_lower(t->irq[0]);
343 void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, qemu_irq *nmi,
344 target_phys_addr_t base)
346 static struct fs_timer_t *t;
347 int timer_regs;
349 t = qemu_mallocz(sizeof *t);
350 if (!t)
351 return;
353 t->bh_t0 = qemu_bh_new(timer0_hit, t);
354 t->bh_t1 = qemu_bh_new(timer1_hit, t);
355 t->bh_wd = qemu_bh_new(watchdog_hit, t);
356 t->ptimer_t0 = ptimer_init(t->bh_t0);
357 t->ptimer_t1 = ptimer_init(t->bh_t1);
358 t->ptimer_wd = ptimer_init(t->bh_wd);
359 t->irq = irqs;
360 t->nmi = nmi;
361 t->env = env;
362 t->base = base;
364 timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t);
365 cpu_register_physical_memory (base, 0x5c, timer_regs);
367 qemu_register_reset(etraxfs_timer_reset, t);