Revision bbaf29c7 hw/etraxfs_timer.c
b/hw/etraxfs_timer.c | ||
---|---|---|
26 | 26 |
#include "hw.h" |
27 | 27 |
#include "qemu-timer.h" |
28 | 28 |
|
29 |
#define D(x) |
|
30 |
|
|
29 | 31 |
void etrax_ack_irq(CPUState *env, uint32_t mask); |
30 | 32 |
|
31 | 33 |
#define R_TIME 0xb001e038 |
... | ... | |
54 | 56 |
CPUState *env; |
55 | 57 |
qemu_irq *irq; |
56 | 58 |
uint32_t mask; |
59 |
struct timeval last; |
|
57 | 60 |
}; |
58 | 61 |
|
59 |
static struct fs_timer_t timer0; |
|
62 |
static struct fs_timer_t timer[2]; |
|
63 |
|
|
64 |
static inline int timer_index(target_phys_addr_t addr) |
|
65 |
{ |
|
66 |
int t = 0; |
|
67 |
if (addr >= 0xb005e000) |
|
68 |
t = 1; |
|
69 |
return t; |
|
70 |
} |
|
60 | 71 |
|
61 | 72 |
/* diff two timevals. Return a single int in us. */ |
62 | 73 |
int diff_timeval_us(struct timeval *a, struct timeval *b) |
... | ... | |
71 | 82 |
|
72 | 83 |
static uint32_t timer_readb (void *opaque, target_phys_addr_t addr) |
73 | 84 |
{ |
74 |
CPUState *env = opaque;
|
|
85 |
CPUState *env; |
|
75 | 86 |
uint32_t r = 0; |
76 |
printf ("%s %x pc=%x\n", __func__, addr, env->pc); |
|
87 |
|
|
88 |
env = opaque; |
|
89 |
D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); |
|
77 | 90 |
return r; |
78 | 91 |
} |
79 | 92 |
static uint32_t timer_readw (void *opaque, target_phys_addr_t addr) |
80 | 93 |
{ |
81 |
CPUState *env = opaque;
|
|
94 |
CPUState *env; |
|
82 | 95 |
uint32_t r = 0; |
83 |
printf ("%s %x pc=%x\n", __func__, addr, env->pc); |
|
96 |
|
|
97 |
env = opaque; |
|
98 |
D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); |
|
84 | 99 |
return r; |
85 | 100 |
} |
86 | 101 |
|
... | ... | |
88 | 103 |
{ |
89 | 104 |
CPUState *env = opaque; |
90 | 105 |
uint32_t r = 0; |
106 |
int t = timer_index(addr); |
|
91 | 107 |
|
92 | 108 |
switch (addr) { |
93 | 109 |
case R_TMR0_DATA: |
94 | 110 |
break; |
95 | 111 |
case R_TMR1_DATA: |
96 |
printf ("R_TMR1_DATA\n");
|
|
112 |
D(printf ("R_TMR1_DATA\n"));
|
|
97 | 113 |
break; |
98 | 114 |
case R_TIME: |
99 | 115 |
{ |
100 |
static struct timeval last; |
|
101 | 116 |
struct timeval now; |
102 | 117 |
gettimeofday(&now, NULL); |
103 |
if (!(last.tv_sec == 0 && last.tv_usec == 0)) { |
|
104 |
r = diff_timeval_us(&now, &last); |
|
118 |
if (!(timer[t].last.tv_sec == 0 |
|
119 |
&& timer[t].last.tv_usec == 0)) { |
|
120 |
r = diff_timeval_us(&now, &timer[t].last); |
|
105 | 121 |
r *= 1000; /* convert to ns. */ |
106 | 122 |
r++; /* make sure we increase for each call. */ |
107 | 123 |
} |
108 |
last = now; |
|
124 |
timer[t].last = now;
|
|
109 | 125 |
break; |
110 | 126 |
} |
111 | 127 |
|
... | ... | |
125 | 141 |
static void |
126 | 142 |
timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) |
127 | 143 |
{ |
128 |
CPUState *env = opaque; |
|
129 |
printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); |
|
144 |
CPUState *env; |
|
145 |
env = opaque; |
|
146 |
D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); |
|
130 | 147 |
} |
131 | 148 |
static void |
132 | 149 |
timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value) |
133 | 150 |
{ |
134 |
CPUState *env = opaque; |
|
135 |
printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); |
|
151 |
CPUState *env; |
|
152 |
env = opaque; |
|
153 |
D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); |
|
136 | 154 |
} |
137 | 155 |
|
138 | 156 |
static void write_ctrl(struct fs_timer_t *t, uint32_t v) |
... | ... | |
165 | 183 |
if (t->limit > 2048) |
166 | 184 |
{ |
167 | 185 |
t->scale = 2048; |
168 |
ptimer_set_period(timer0.ptimer, freq_hz / t->scale);
|
|
186 |
ptimer_set_period(t->ptimer, freq_hz / t->scale);
|
|
169 | 187 |
} |
170 | 188 |
|
171 | 189 |
printf ("op=%d\n", op); |
... | ... | |
187 | 205 |
} |
188 | 206 |
} |
189 | 207 |
|
190 |
static void timer_ack_irq(void)
|
|
208 |
static void timer_ack_irq(struct fs_timer_t *t)
|
|
191 | 209 |
{ |
192 |
if (!(r_intr & timer0.mask & rw_intr_mask)) {
|
|
193 |
qemu_irq_lower(timer0.irq[0]);
|
|
194 |
etrax_ack_irq(timer0.env, 1 << 0x1b);
|
|
210 |
if (!(r_intr & t->mask & rw_intr_mask)) {
|
|
211 |
qemu_irq_lower(t->irq[0]);
|
|
212 |
etrax_ack_irq(t->env, 1 << 0x1b);
|
|
195 | 213 |
} |
196 | 214 |
} |
197 | 215 |
|
... | ... | |
199 | 217 |
timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
200 | 218 |
{ |
201 | 219 |
CPUState *env = opaque; |
202 |
printf ("%s %x %x pc=%x\n", |
|
203 |
__func__, addr, value, env->pc); |
|
220 |
int t = timer_index(addr); |
|
221 |
|
|
222 |
D(printf ("%s %x %x pc=%x\n", |
|
223 |
__func__, addr, value, env->pc)); |
|
204 | 224 |
switch (addr) |
205 | 225 |
{ |
206 | 226 |
case RW_TMR0_DIV: |
207 |
printf ("RW_TMR0_DIV=%x\n", value);
|
|
208 |
timer0.limit = value;
|
|
227 |
D(printf ("RW_TMR0_DIV=%x\n", value));
|
|
228 |
timer[t].limit = value;
|
|
209 | 229 |
break; |
210 | 230 |
case RW_TMR0_CTRL: |
211 |
printf ("RW_TMR0_CTRL=%x\n", value);
|
|
212 |
write_ctrl(&timer0, value);
|
|
231 |
D(printf ("RW_TMR0_CTRL=%x\n", value));
|
|
232 |
write_ctrl(&timer[t], value);
|
|
213 | 233 |
break; |
214 | 234 |
case RW_TMR1_DIV: |
215 |
printf ("RW_TMR1_DIV=%x\n", value);
|
|
235 |
D(printf ("RW_TMR1_DIV=%x\n", value));
|
|
216 | 236 |
break; |
217 | 237 |
case RW_TMR1_CTRL: |
218 |
printf ("RW_TMR1_CTRL=%x\n", value);
|
|
238 |
D(printf ("RW_TMR1_CTRL=%x\n", value));
|
|
219 | 239 |
break; |
220 | 240 |
case RW_INTR_MASK: |
221 |
printf ("RW_INTR_MASK=%x\n", value);
|
|
241 |
D(printf ("RW_INTR_MASK=%x\n", value));
|
|
222 | 242 |
rw_intr_mask = value; |
223 | 243 |
break; |
224 | 244 |
case RW_ACK_INTR: |
225 | 245 |
r_intr &= ~value; |
226 |
timer_ack_irq(); |
|
246 |
timer_ack_irq(&timer[t]);
|
|
227 | 247 |
break; |
228 | 248 |
default: |
229 | 249 |
printf ("%s %x %x pc=%x\n", |
... | ... | |
247 | 267 |
static void timer_irq(void *opaque) |
248 | 268 |
{ |
249 | 269 |
struct fs_timer_t *t = opaque; |
250 |
|
|
251 | 270 |
r_intr |= t->mask; |
252 | 271 |
if (t->mask & rw_intr_mask) { |
253 | 272 |
qemu_irq_raise(t->irq[0]); |
... | ... | |
258 | 277 |
{ |
259 | 278 |
int timer_regs; |
260 | 279 |
|
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; |
|
280 |
timer[0].bh = qemu_bh_new(timer_irq, &timer[0]); |
|
281 |
timer[0].ptimer = ptimer_init(timer[0].bh); |
|
282 |
timer[0].irq = irqs + 0x1b; |
|
283 |
timer[0].mask = 1; |
|
284 |
timer[0].env = env; |
|
285 |
|
|
286 |
timer[1].bh = qemu_bh_new(timer_irq, &timer[1]); |
|
287 |
timer[1].ptimer = ptimer_init(timer[1].bh); |
|
288 |
timer[1].irq = irqs + 0x1b; |
|
289 |
timer[1].mask = 1; |
|
290 |
timer[1].env = env; |
|
266 | 291 |
|
267 | 292 |
timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env); |
268 | 293 |
cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs); |
294 |
cpu_register_physical_memory (0xb005e000, 0x5c, timer_regs); |
|
269 | 295 |
} |
Also available in: Unified diff