Lines Matching +full:- +full:m

2  * ARM CMSDK APB dual-timer emulation
13 * This is a model of the "APB dual-input timer" which is part of the Cortex-M
14 * System Design Kit (CMSDK) and documented in the Cortex-M System
16 * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
26 #include "hw/qdev-properties.h"
28 #include "hw/qdev-clock.h"
29 #include "hw/timer/cmsdk-apb-dualtimer.h"
83 static bool cmsdk_dualtimermod_intstatus(CMSDKAPBDualTimerModule *m) in cmsdk_dualtimermod_intstatus() argument
86 return m->intstatus && (m->control & R_CONTROL_INTEN_MASK); in cmsdk_dualtimermod_intstatus()
93 if (s->timeritcr) { in cmsdk_apb_dualtimer_update()
95 timint1 = s->timeritop & R_TIMERITOP_TIMINT1_MASK; in cmsdk_apb_dualtimer_update()
96 timint2 = s->timeritop & R_TIMERITOP_TIMINT2_MASK; in cmsdk_apb_dualtimer_update()
98 timint1 = cmsdk_dualtimermod_intstatus(&s->timermod[0]); in cmsdk_apb_dualtimer_update()
99 timint2 = cmsdk_dualtimermod_intstatus(&s->timermod[1]); in cmsdk_apb_dualtimer_update()
104 qemu_set_irq(s->timermod[0].timerint, timint1); in cmsdk_apb_dualtimer_update()
105 qemu_set_irq(s->timermod[1].timerint, timint2); in cmsdk_apb_dualtimer_update()
106 qemu_set_irq(s->timerintc, timintc); in cmsdk_apb_dualtimer_update()
109 static int cmsdk_dualtimermod_divisor(CMSDKAPBDualTimerModule *m) in cmsdk_dualtimermod_divisor() argument
112 switch (FIELD_EX32(m->control, CONTROL, PRESCALE)) { in cmsdk_dualtimermod_divisor()
125 static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m, in cmsdk_dualtimermod_write_control() argument
131 ptimer_transaction_begin(m->timer); in cmsdk_dualtimermod_write_control()
135 changed = m->control ^ newctrl; in cmsdk_dualtimermod_write_control()
139 ptimer_stop(m->timer); in cmsdk_dualtimermod_write_control()
158 "CMSDK APB dual-timer: CONTROL.PRESCALE==0b11" in cmsdk_dualtimermod_write_control()
165 ptimer_set_period_from_clock(m->timer, m->parent->timclk, divisor); in cmsdk_dualtimermod_write_control()
172 load = m->load; in cmsdk_dualtimermod_write_control()
174 /* Free-running: counter wraps around */ in cmsdk_dualtimermod_write_control()
175 load = ptimer_get_limit(m->timer); in cmsdk_dualtimermod_write_control()
176 if (!(m->control & R_CONTROL_SIZE_MASK)) { in cmsdk_dualtimermod_write_control()
177 load = deposit32(m->load, 0, 16, load); in cmsdk_dualtimermod_write_control()
179 m->load = load; in cmsdk_dualtimermod_write_control()
182 if (!(m->control & R_CONTROL_SIZE_MASK)) { in cmsdk_dualtimermod_write_control()
185 ptimer_set_limit(m->timer, load, 0); in cmsdk_dualtimermod_write_control()
192 value = ptimer_get_count(m->timer); in cmsdk_dualtimermod_write_control()
193 load = ptimer_get_limit(m->timer); in cmsdk_dualtimermod_write_control()
195 /* 16 -> 32, top half of VALUE is in struct field */ in cmsdk_dualtimermod_write_control()
196 value = deposit32(m->value, 0, 16, value); in cmsdk_dualtimermod_write_control()
198 /* 32 -> 16: save top half to struct field and truncate */ in cmsdk_dualtimermod_write_control()
199 m->value = value; in cmsdk_dualtimermod_write_control()
206 load = deposit32(m->load, 0, 16, load); in cmsdk_dualtimermod_write_control()
208 m->load = load; in cmsdk_dualtimermod_write_control()
212 /* Free-running, timer limit is set to give wraparound */ in cmsdk_dualtimermod_write_control()
219 ptimer_set_count(m->timer, value); in cmsdk_dualtimermod_write_control()
220 ptimer_set_limit(m->timer, load, 0); in cmsdk_dualtimermod_write_control()
227 * in case the timer was an expired one-shot timer that has in cmsdk_dualtimermod_write_control()
228 * now been changed into a free-running or periodic timer. in cmsdk_dualtimermod_write_control()
230 ptimer_run(m->timer, !!(newctrl & R_CONTROL_ONESHOT_MASK)); in cmsdk_dualtimermod_write_control()
233 m->control = newctrl; in cmsdk_dualtimermod_write_control()
235 ptimer_transaction_commit(m->timer); in cmsdk_dualtimermod_write_control()
247 r = s->timeritcr; in cmsdk_apb_dualtimer_read()
250 r = timer_id[(offset - A_PID4) / 4]; in cmsdk_apb_dualtimer_read()
255 "CMSDK APB dual-timer read: bad offset %x\n", in cmsdk_apb_dualtimer_read()
262 CMSDKAPBDualTimerModule *m; in cmsdk_apb_dualtimer_read() local
264 if (timer >= ARRAY_SIZE(s->timermod)) { in cmsdk_apb_dualtimer_read()
268 m = &s->timermod[timer]; in cmsdk_apb_dualtimer_read()
273 if (m->control & R_CONTROL_MODE_MASK) { in cmsdk_apb_dualtimer_read()
276 * just the low 16 bits of it if the timer is in 16-bit mode) in cmsdk_apb_dualtimer_read()
278 r = ptimer_get_limit(m->timer); in cmsdk_apb_dualtimer_read()
279 if (!(m->control & R_CONTROL_SIZE_MASK)) { in cmsdk_apb_dualtimer_read()
280 r = deposit32(m->load, 0, 16, r); in cmsdk_apb_dualtimer_read()
283 /* Free-running: LOAD register value is just in m->load */ in cmsdk_apb_dualtimer_read()
284 r = m->load; in cmsdk_apb_dualtimer_read()
288 r = ptimer_get_count(m->timer); in cmsdk_apb_dualtimer_read()
289 if (!(m->control & R_CONTROL_SIZE_MASK)) { in cmsdk_apb_dualtimer_read()
290 r = deposit32(m->value, 0, 16, r); in cmsdk_apb_dualtimer_read()
294 r = m->control; in cmsdk_apb_dualtimer_read()
297 r = m->intstatus; in cmsdk_apb_dualtimer_read()
300 r = cmsdk_dualtimermod_intstatus(m); in cmsdk_apb_dualtimer_read()
321 s->timeritcr = value & R_TIMERITCR_VALID_MASK; in cmsdk_apb_dualtimer_write()
325 s->timeritop = value & R_TIMERITOP_VALID_MASK; in cmsdk_apb_dualtimer_write()
331 "CMSDK APB dual-timer write: bad offset %x\n", in cmsdk_apb_dualtimer_write()
337 CMSDKAPBDualTimerModule *m; in cmsdk_apb_dualtimer_write() local
339 if (timer >= ARRAY_SIZE(s->timermod)) { in cmsdk_apb_dualtimer_write()
343 m = &s->timermod[timer]; in cmsdk_apb_dualtimer_write()
348 m->load = value; in cmsdk_apb_dualtimer_write()
349 m->value = value; in cmsdk_apb_dualtimer_write()
350 if (!(m->control & R_CONTROL_SIZE_MASK)) { in cmsdk_apb_dualtimer_write()
353 ptimer_transaction_begin(m->timer); in cmsdk_apb_dualtimer_write()
354 if (!(m->control & R_CONTROL_MODE_MASK)) { in cmsdk_apb_dualtimer_write()
356 * In free-running mode this won't set the limit but will in cmsdk_apb_dualtimer_write()
359 ptimer_set_count(m->timer, value); in cmsdk_apb_dualtimer_write()
362 ptimer_stop(m->timer); in cmsdk_apb_dualtimer_write()
364 ptimer_set_limit(m->timer, value, 1); in cmsdk_apb_dualtimer_write()
365 if (value && (m->control & R_CONTROL_ENABLE_MASK)) { in cmsdk_apb_dualtimer_write()
366 /* Force possibly-expired oneshot timer to restart */ in cmsdk_apb_dualtimer_write()
367 ptimer_run(m->timer, 1); in cmsdk_apb_dualtimer_write()
370 ptimer_transaction_commit(m->timer); in cmsdk_apb_dualtimer_write()
374 m->load = value; in cmsdk_apb_dualtimer_write()
375 if (!(m->control & R_CONTROL_MODE_MASK)) { in cmsdk_apb_dualtimer_write()
376 /* In free-running mode there is no limit */ in cmsdk_apb_dualtimer_write()
379 if (!(m->control & R_CONTROL_SIZE_MASK)) { in cmsdk_apb_dualtimer_write()
382 ptimer_transaction_begin(m->timer); in cmsdk_apb_dualtimer_write()
383 ptimer_set_limit(m->timer, value, 0); in cmsdk_apb_dualtimer_write()
384 ptimer_transaction_commit(m->timer); in cmsdk_apb_dualtimer_write()
387 cmsdk_dualtimermod_write_control(m, value); in cmsdk_apb_dualtimer_write()
391 m->intstatus = 0; in cmsdk_apb_dualtimer_write()
404 /* byte/halfword accesses are just zero-padded on reads and writes */
413 CMSDKAPBDualTimerModule *m = opaque; in cmsdk_dualtimermod_tick() local
415 m->intstatus = 1; in cmsdk_dualtimermod_tick()
416 cmsdk_apb_dualtimer_update(m->parent); in cmsdk_dualtimermod_tick()
419 static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m) in cmsdk_dualtimermod_reset() argument
421 m->control = R_CONTROL_INTEN_MASK; in cmsdk_dualtimermod_reset()
422 m->intstatus = 0; in cmsdk_dualtimermod_reset()
423 m->load = 0; in cmsdk_dualtimermod_reset()
424 m->value = 0xffffffff; in cmsdk_dualtimermod_reset()
425 ptimer_transaction_begin(m->timer); in cmsdk_dualtimermod_reset()
426 ptimer_stop(m->timer); in cmsdk_dualtimermod_reset()
428 * We start in free-running mode, with VALUE at 0xffffffff, and in cmsdk_dualtimermod_reset()
429 * in 16-bit counter mode. This means that the ptimer count and in cmsdk_dualtimermod_reset()
432 ptimer_set_limit(m->timer, 0xffff, 1); in cmsdk_dualtimermod_reset()
433 ptimer_set_period_from_clock(m->timer, m->parent->timclk, in cmsdk_dualtimermod_reset()
434 cmsdk_dualtimermod_divisor(m)); in cmsdk_dualtimermod_reset()
435 ptimer_transaction_commit(m->timer); in cmsdk_dualtimermod_reset()
445 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) { in cmsdk_apb_dualtimer_reset()
446 cmsdk_dualtimermod_reset(&s->timermod[i]); in cmsdk_apb_dualtimer_reset()
448 s->timeritcr = 0; in cmsdk_apb_dualtimer_reset()
449 s->timeritop = 0; in cmsdk_apb_dualtimer_reset()
457 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) { in cmsdk_apb_dualtimer_clk_update()
458 CMSDKAPBDualTimerModule *m = &s->timermod[i]; in cmsdk_apb_dualtimer_clk_update() local
459 ptimer_transaction_begin(m->timer); in cmsdk_apb_dualtimer_clk_update()
460 ptimer_set_period_from_clock(m->timer, m->parent->timclk, in cmsdk_apb_dualtimer_clk_update()
461 cmsdk_dualtimermod_divisor(m)); in cmsdk_apb_dualtimer_clk_update()
462 ptimer_transaction_commit(m->timer); in cmsdk_apb_dualtimer_clk_update()
472 memory_region_init_io(&s->iomem, obj, &cmsdk_apb_dualtimer_ops, in cmsdk_apb_dualtimer_init()
473 s, "cmsdk-apb-dualtimer", 0x1000); in cmsdk_apb_dualtimer_init()
474 sysbus_init_mmio(sbd, &s->iomem); in cmsdk_apb_dualtimer_init()
475 sysbus_init_irq(sbd, &s->timerintc); in cmsdk_apb_dualtimer_init()
477 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) { in cmsdk_apb_dualtimer_init()
478 sysbus_init_irq(sbd, &s->timermod[i].timerint); in cmsdk_apb_dualtimer_init()
480 s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK", in cmsdk_apb_dualtimer_init()
490 if (!clock_has_source(s->timclk)) { in cmsdk_apb_dualtimer_realize()
495 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) { in cmsdk_apb_dualtimer_realize()
496 CMSDKAPBDualTimerModule *m = &s->timermod[i]; in cmsdk_apb_dualtimer_realize() local
498 m->parent = s; in cmsdk_apb_dualtimer_realize()
499 m->timer = ptimer_init(cmsdk_dualtimermod_tick, m, in cmsdk_apb_dualtimer_realize()
508 .name = "cmsdk-apb-dualtimer-module",
522 .name = "cmsdk-apb-dualtimer",
541 dc->realize = cmsdk_apb_dualtimer_realize; in cmsdk_apb_dualtimer_class_init()
542 dc->vmsd = &cmsdk_apb_dualtimer_vmstate; in cmsdk_apb_dualtimer_class_init()