Revision 3b1fd90e hw/etraxfs_timer.c
b/hw/etraxfs_timer.c | ||
---|---|---|
21 | 21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
22 | 22 |
* THE SOFTWARE. |
23 | 23 |
*/ |
24 |
#include <stdio.h> |
|
25 |
#include <sys/time.h> |
|
26 |
#include "hw.h" |
|
24 |
#include "sysbus.h" |
|
27 | 25 |
#include "sysemu.h" |
28 | 26 |
#include "qemu-timer.h" |
29 |
#include "etraxfs.h" |
|
30 | 27 |
|
31 | 28 |
#define D(x) |
32 | 29 |
|
... | ... | |
44 | 41 |
#define R_INTR 0x50 |
45 | 42 |
#define R_MASKED_INTR 0x54 |
46 | 43 |
|
47 |
struct fs_timer_t {
|
|
48 |
CPUState *env;
|
|
49 |
qemu_irq *irq;
|
|
50 |
qemu_irq *nmi;
|
|
44 |
struct etrax_timer {
|
|
45 |
SysBusDevice busdev;
|
|
46 |
qemu_irq irq; |
|
47 |
qemu_irq nmi; |
|
51 | 48 |
|
52 | 49 |
QEMUBH *bh_t0; |
53 | 50 |
QEMUBH *bh_t1; |
... | ... | |
78 | 75 |
|
79 | 76 |
static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) |
80 | 77 |
{ |
81 |
struct fs_timer_t *t = opaque;
|
|
78 |
struct etrax_timer *t = opaque;
|
|
82 | 79 |
uint32_t r = 0; |
83 | 80 |
|
84 | 81 |
switch (addr) { |
... | ... | |
105 | 102 |
} |
106 | 103 |
|
107 | 104 |
#define TIMER_SLOWDOWN 1 |
108 |
static void update_ctrl(struct fs_timer_t *t, int tnum)
|
|
105 |
static void update_ctrl(struct etrax_timer *t, int tnum)
|
|
109 | 106 |
{ |
110 | 107 |
unsigned int op; |
111 | 108 |
unsigned int freq; |
... | ... | |
172 | 169 |
} |
173 | 170 |
} |
174 | 171 |
|
175 |
static void timer_update_irq(struct fs_timer_t *t)
|
|
172 |
static void timer_update_irq(struct etrax_timer *t)
|
|
176 | 173 |
{ |
177 | 174 |
t->r_intr &= ~(t->rw_ack_intr); |
178 | 175 |
t->r_masked_intr = t->r_intr & t->rw_intr_mask; |
179 | 176 |
|
180 | 177 |
D(printf("%s: masked_intr=%x\n", __func__, t->r_masked_intr)); |
181 |
qemu_set_irq(t->irq[0], !!t->r_masked_intr);
|
|
178 |
qemu_set_irq(t->irq, !!t->r_masked_intr); |
|
182 | 179 |
} |
183 | 180 |
|
184 | 181 |
static void timer0_hit(void *opaque) |
185 | 182 |
{ |
186 |
struct fs_timer_t *t = opaque;
|
|
183 |
struct etrax_timer *t = opaque;
|
|
187 | 184 |
t->r_intr |= 1; |
188 | 185 |
timer_update_irq(t); |
189 | 186 |
} |
190 | 187 |
|
191 | 188 |
static void timer1_hit(void *opaque) |
192 | 189 |
{ |
193 |
struct fs_timer_t *t = opaque;
|
|
190 |
struct etrax_timer *t = opaque;
|
|
194 | 191 |
t->r_intr |= 2; |
195 | 192 |
timer_update_irq(t); |
196 | 193 |
} |
197 | 194 |
|
198 | 195 |
static void watchdog_hit(void *opaque) |
199 | 196 |
{ |
200 |
struct fs_timer_t *t = opaque;
|
|
197 |
struct etrax_timer *t = opaque;
|
|
201 | 198 |
if (t->wd_hits == 0) { |
202 | 199 |
/* real hw gives a single tick before reseting but we are |
203 | 200 |
a bit friendlier to compensate for our slower execution. */ |
204 | 201 |
ptimer_set_count(t->ptimer_wd, 10); |
205 | 202 |
ptimer_run(t->ptimer_wd, 1); |
206 |
qemu_irq_raise(t->nmi[0]);
|
|
203 |
qemu_irq_raise(t->nmi); |
|
207 | 204 |
} |
208 | 205 |
else |
209 | 206 |
qemu_system_reset_request(); |
... | ... | |
211 | 208 |
t->wd_hits++; |
212 | 209 |
} |
213 | 210 |
|
214 |
static inline void timer_watchdog_update(struct fs_timer_t *t, uint32_t value)
|
|
211 |
static inline void timer_watchdog_update(struct etrax_timer *t, uint32_t value)
|
|
215 | 212 |
{ |
216 | 213 |
unsigned int wd_en = t->rw_wd_ctrl & (1 << 8); |
217 | 214 |
unsigned int wd_key = t->rw_wd_ctrl >> 9; |
... | ... | |
230 | 227 |
wd_en, new_key, wd_key, new_cmd, wd_cnt)); |
231 | 228 |
|
232 | 229 |
if (t->wd_hits) |
233 |
qemu_irq_lower(t->nmi[0]);
|
|
230 |
qemu_irq_lower(t->nmi); |
|
234 | 231 |
|
235 | 232 |
t->wd_hits = 0; |
236 | 233 |
|
... | ... | |
249 | 246 |
static void |
250 | 247 |
timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
251 | 248 |
{ |
252 |
struct fs_timer_t *t = opaque;
|
|
249 |
struct etrax_timer *t = opaque;
|
|
253 | 250 |
|
254 | 251 |
switch (addr) |
255 | 252 |
{ |
... | ... | |
301 | 298 |
|
302 | 299 |
static void etraxfs_timer_reset(void *opaque) |
303 | 300 |
{ |
304 |
struct fs_timer_t *t = opaque;
|
|
301 |
struct etrax_timer *t = opaque;
|
|
305 | 302 |
|
306 | 303 |
ptimer_stop(t->ptimer_t0); |
307 | 304 |
ptimer_stop(t->ptimer_t1); |
... | ... | |
309 | 306 |
t->rw_wd_ctrl = 0; |
310 | 307 |
t->r_intr = 0; |
311 | 308 |
t->rw_intr_mask = 0; |
312 |
qemu_irq_lower(t->irq[0]);
|
|
309 |
qemu_irq_lower(t->irq); |
|
313 | 310 |
} |
314 | 311 |
|
315 |
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, qemu_irq *nmi, |
|
316 |
target_phys_addr_t base) |
|
312 |
static void etraxfs_timer_init(SysBusDevice *dev) |
|
317 | 313 |
{ |
318 |
static struct fs_timer_t *t;
|
|
314 |
struct etrax_timer *t = FROM_SYSBUS(typeof (*t), dev);
|
|
319 | 315 |
int timer_regs; |
320 | 316 |
|
321 |
t = qemu_mallocz(sizeof *t); |
|
322 |
|
|
323 | 317 |
t->bh_t0 = qemu_bh_new(timer0_hit, t); |
324 | 318 |
t->bh_t1 = qemu_bh_new(timer1_hit, t); |
325 | 319 |
t->bh_wd = qemu_bh_new(watchdog_hit, t); |
326 | 320 |
t->ptimer_t0 = ptimer_init(t->bh_t0); |
327 | 321 |
t->ptimer_t1 = ptimer_init(t->bh_t1); |
328 | 322 |
t->ptimer_wd = ptimer_init(t->bh_wd); |
329 |
t->irq = irqs; |
|
330 |
t->nmi = nmi;
|
|
331 |
t->env = env;
|
|
323 |
|
|
324 |
sysbus_init_irq(dev, &t->irq);
|
|
325 |
sysbus_init_irq(dev, &t->nmi);
|
|
332 | 326 |
|
333 | 327 |
timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t); |
334 |
cpu_register_physical_memory (base, 0x5c, timer_regs);
|
|
328 |
sysbus_init_mmio(dev, 0x5c, timer_regs);
|
|
335 | 329 |
|
336 | 330 |
qemu_register_reset(etraxfs_timer_reset, t); |
337 | 331 |
} |
332 |
|
|
333 |
static void etraxfs_timer_register(void) |
|
334 |
{ |
|
335 |
sysbus_register_dev("etraxfs,timer", sizeof (struct etrax_timer), |
|
336 |
etraxfs_timer_init); |
|
337 |
} |
|
338 |
|
|
339 |
device_init(etraxfs_timer_register) |
Also available in: Unified diff