Update Changelog with new Xscale platforms and vmsvga.
[qemu] / hw / etraxfs_timer.c
1 /*
2  * QEMU ETRAX System Emulator
3  *
4  * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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.
23  */
24 #include <stdio.h>
25 #include <sys/time.h>
26 #include "hw.h"
27 #include "qemu-timer.h"
28
29 void etrax_ack_irq(CPUState *env, uint32_t mask);
30
31 #define R_TIME 0xb001e038
32 #define RW_TMR0_DIV 0xb001e000
33 #define R_TMR0_DATA 0xb001e004
34 #define RW_TMR0_CTRL 0xb001e008
35 #define RW_TMR1_DIV 0xb001e010
36 #define R_TMR1_DATA 0xb001e014
37 #define RW_TMR1_CTRL 0xb001e018
38
39 #define RW_INTR_MASK 0xb001e048
40 #define RW_ACK_INTR 0xb001e04c
41 #define R_INTR 0xb001e050
42 #define R_MASKED_INTR 0xb001e054
43
44
45 uint32_t rw_intr_mask;
46 uint32_t rw_ack_intr;
47 uint32_t r_intr;
48
49 struct fs_timer_t {
50         QEMUBH *bh;
51         unsigned int limit;
52         int scale;
53         ptimer_state *ptimer;
54         CPUState *env;
55         qemu_irq *irq;
56         uint32_t mask;
57 };
58
59 static struct fs_timer_t timer0;
60
61 /* diff two timevals.  Return a single int in us. */
62 int diff_timeval_us(struct timeval *a, struct timeval *b)
63 {
64         int diff;
65
66         /* assume these values are signed.  */
67         diff = (a->tv_sec - b->tv_sec) * 1000 * 1000;
68         diff += (a->tv_usec - b->tv_usec);
69         return diff;
70 }
71
72 static uint32_t timer_readb (void *opaque, target_phys_addr_t addr)
73 {
74         CPUState *env = opaque;
75         uint32_t r = 0;
76         printf ("%s %x pc=%x\n", __func__, addr, env->pc);
77         return r;
78 }
79 static uint32_t timer_readw (void *opaque, target_phys_addr_t addr)
80 {
81         CPUState *env = opaque;
82         uint32_t r = 0;
83         printf ("%s %x pc=%x\n", __func__, addr, env->pc);
84         return r;
85 }
86
87 static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
88 {
89         CPUState *env = opaque;
90         uint32_t r = 0;
91
92         switch (addr) {
93         case R_TMR0_DATA:
94                 break;
95         case R_TMR1_DATA:
96                 printf ("R_TMR1_DATA\n");
97                 break;
98         case R_TIME:
99         {
100                 static struct timeval last;
101                 struct timeval now;
102                 gettimeofday(&now, NULL);
103                 if (!(last.tv_sec == 0 && last.tv_usec == 0)) {
104                         r = diff_timeval_us(&now, &last);
105                         r *= 1000; /* convert to ns.  */
106                         r++; /* make sure we increase for each call.  */
107                 }
108                 last = now;
109                 break;
110         }
111
112         case RW_INTR_MASK:
113                 r = rw_intr_mask;
114                 break;
115         case R_MASKED_INTR:
116                 r = r_intr & rw_intr_mask;
117                 break;
118         default:
119                 printf ("%s %x p=%x\n", __func__, addr, env->pc);
120                 break;
121         }
122         return r;
123 }
124
125 static void
126 timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
127 {
128         CPUState *env = opaque;
129         printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
130 }
131 static void
132 timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
133 {
134         CPUState *env = opaque;
135         printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
136 }
137
138 static void write_ctrl(struct fs_timer_t *t, uint32_t v)
139 {
140         int op;
141         int freq;
142         int freq_hz;
143
144         op = v & 3;
145         freq = v >> 2;
146         freq_hz = 32000000;
147
148         switch (freq)
149         {
150         case 0:
151         case 1:
152                 printf ("extern or disabled timer clock?\n");
153                 break;
154         case 4: freq_hz =  29493000; break;
155         case 5: freq_hz =  32000000; break;
156         case 6: freq_hz =  32768000; break;
157         case 7: freq_hz = 100000000; break;
158         default:
159                 abort();
160                 break;
161         }
162
163         printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit);
164         t->scale = 0;
165         if (t->limit > 2048)
166         {
167                 t->scale = 2048;
168                 ptimer_set_period(timer0.ptimer, freq_hz / t->scale);
169         }
170
171         printf ("op=%d\n", op);
172         switch (op)
173         {
174                 case 0:
175                         printf ("limit=%d %d\n", t->limit, t->limit/t->scale);
176                         ptimer_set_limit(t->ptimer, t->limit / t->scale, 1);
177                         break;
178                 case 1:
179                         ptimer_stop(t->ptimer);
180                         break;
181                 case 2:
182                         ptimer_run(t->ptimer, 0);
183                         break;
184                 default:
185                         abort();
186                         break;
187         }
188 }
189
190 static void timer_ack_irq(void)
191 {
192         if (!(r_intr & timer0.mask & rw_intr_mask)) {
193                 qemu_irq_lower(timer0.irq[0]);
194                 etrax_ack_irq(timer0.env, 1 << 0x1b);
195         }
196 }
197
198 static void
199 timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
200 {
201         CPUState *env = opaque;
202         printf ("%s %x %x pc=%x\n",
203                 __func__, addr, value, env->pc);
204         switch (addr)
205         {
206                 case RW_TMR0_DIV:
207                         printf ("RW_TMR0_DIV=%x\n", value);
208                         timer0.limit = value;
209                         break;
210                 case RW_TMR0_CTRL:
211                         printf ("RW_TMR0_CTRL=%x\n", value);
212                         write_ctrl(&timer0, value);
213                         break;
214                 case RW_TMR1_DIV:
215                         printf ("RW_TMR1_DIV=%x\n", value);
216                         break;
217                 case RW_TMR1_CTRL:
218                         printf ("RW_TMR1_CTRL=%x\n", value);
219                         break;
220                 case RW_INTR_MASK:
221                         printf ("RW_INTR_MASK=%x\n", value);
222                         rw_intr_mask = value;
223                         break;
224                 case RW_ACK_INTR:
225                         r_intr &= ~value;
226                         timer_ack_irq();
227                         break;
228                 default:
229                         printf ("%s %x %x pc=%x\n",
230                                 __func__, addr, value, env->pc);
231                         break;
232         }
233 }
234
235 static CPUReadMemoryFunc *timer_read[] = {
236     &timer_readb,
237     &timer_readw,
238     &timer_readl,
239 };
240
241 static CPUWriteMemoryFunc *timer_write[] = {
242     &timer_writeb,
243     &timer_writew,
244     &timer_writel,
245 };
246
247 static void timer_irq(void *opaque)
248 {
249         struct fs_timer_t *t = opaque;
250
251         r_intr |= t->mask;
252         if (t->mask & rw_intr_mask) {
253                 qemu_irq_raise(t->irq[0]);
254         }
255 }
256
257 void etraxfs_timer_init(CPUState *env, qemu_irq *irqs)
258 {
259         int timer_regs;
260
261         timer0.bh = qemu_bh_new(timer_irq, &timer0);
262         timer0.ptimer = ptimer_init(timer0.bh);
263         timer0.irq = irqs + 0x1b;
264         timer0.mask = 1;
265         timer0.env = env;
266
267         timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env);
268         cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs);
269 }