static int xilinx_timer_init(SysBusDevice *dev) { struct timerblock *t = FROM_SYSBUS(typeof (*t), dev); unsigned int i; /* All timers share a single irq line. */ sysbus_init_irq(dev, &t->irq); /* Init all the ptimers. */ t->timers = g_malloc0(sizeof t->timers[0] * num_timers(t)); for (i = 0; i < num_timers(t); i++) { struct xlx_timer *xt = &t->timers[i]; xt->parent = t; xt->nr = i; xt->bh = qemu_bh_new(timer_hit, xt); xt->ptimer = ptimer_init(xt->bh); ptimer_set_freq(xt->ptimer, t->freq_hz); } memory_region_init_io(&t->mmio, &timer_ops, t, "xlnx.xps-timer", R_MAX * 4 * num_timers(t)); sysbus_init_mmio(dev, &t->mmio); return 0; }
static void grlib_gptimer_reset(DeviceState *d) { GPTimerUnit *unit = container_of(d, GPTimerUnit, busdev.qdev); int i = 0; assert(unit != NULL); unit->scaler = 0; unit->reload = 0; unit->config = 0; unit->config = unit->nr_timers; unit->config |= unit->irq_line << 3; unit->config |= 1 << 8; /* separate interrupt */ unit->config |= 1 << 9; /* Disable timer freeze */ for (i = 0; i < unit->nr_timers; i++) { GPTimer *timer = &unit->timers[i]; timer->counter = 0; timer->reload = 0; timer->config = 0; ptimer_stop(timer->ptimer); ptimer_set_count(timer->ptimer, 0); ptimer_set_freq(timer->ptimer, unit->freq_hz); } }
static int grlib_gptimer_init(SysBusDevice *dev) { GPTimerUnit *unit = FROM_SYSBUS(typeof(*unit), dev); unsigned int i; assert(unit->nr_timers > 0); assert(unit->nr_timers <= GPTIMER_MAX_TIMERS); unit->timers = g_malloc0(sizeof unit->timers[0] * unit->nr_timers); for (i = 0; i < unit->nr_timers; i++) { GPTimer *timer = &unit->timers[i]; timer->unit = unit; timer->bh = qemu_bh_new(grlib_gptimer_hit, timer); timer->ptimer = ptimer_init(timer->bh); timer->id = i; /* One IRQ line for each timer */ sysbus_init_irq(dev, &timer->irq); ptimer_set_freq(timer->ptimer, unit->freq_hz); } memory_region_init_io(&unit->iomem, &grlib_gptimer_ops, unit, "gptimer", UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers); sysbus_init_mmio(dev, &unit->iomem); return 0; }
static inline void timer_watchdog_update(struct etrax_timer *t, uint32_t value) { unsigned int wd_en = t->rw_wd_ctrl & (1 << 8); unsigned int wd_key = t->rw_wd_ctrl >> 9; unsigned int wd_cnt = t->rw_wd_ctrl & 511; unsigned int new_key = value >> 9 & ((1 << 7) - 1); unsigned int new_cmd = (value >> 8) & 1; /* If the watchdog is enabled, they written key must match the complement of the previous. */ wd_key = ~wd_key & ((1 << 7) - 1); if (wd_en && wd_key != new_key) return; D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n", wd_en, new_key, wd_key, new_cmd, wd_cnt)); if (t->wd_hits) qemu_irq_lower(t->nmi); t->wd_hits = 0; ptimer_set_freq(t->ptimer_wd, 760); if (wd_cnt == 0) wd_cnt = 256; ptimer_set_count(t->ptimer_wd, wd_cnt); if (new_cmd) ptimer_run(t->ptimer_wd, 1); else ptimer_stop(t->ptimer_wd); t->rw_wd_ctrl = value; }
static void imx_epit_set_freq(IMXEPITState *s) { uint32_t clksrc; uint32_t prescaler; uint32_t freq; clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2); prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12); freq = imx_clock_frequency(s->ccm, imx_epit_clocks[clksrc]) / prescaler; s->freq = freq; DPRINTF("Setting ptimer frequency to %u\n", freq); if (freq) { ptimer_set_freq(s->timer_reload, freq); ptimer_set_freq(s->timer_cmp, freq); } }
static int marin_timer_init(SysBusDevice *dev) { MarinTimerState *s = MARIN_TIMER(dev); sysbus_init_irq(dev, &s->irq); s->bh = qemu_bh_new(marin_timer_tick, s); s->ptimer = ptimer_init(s->bh); ptimer_set_freq(s->ptimer, 50 * 1000 * 1000); return 0; }
static int milkymist_sysctl_init(SysBusDevice *dev) { MilkymistSysctlState *s = FROM_SYSBUS(typeof(*s), dev); sysbus_init_irq(dev, &s->gpio_irq); sysbus_init_irq(dev, &s->timer0_irq); sysbus_init_irq(dev, &s->timer1_irq); s->bh0 = qemu_bh_new(timer0_hit, s); s->bh1 = qemu_bh_new(timer1_hit, s); s->ptimer0 = ptimer_init(s->bh0); s->ptimer1 = ptimer_init(s->bh1); ptimer_set_freq(s->ptimer0, s->freq_hz); ptimer_set_freq(s->ptimer1, s->freq_hz); memory_region_init_io(&s->regs_region, &sysctl_mmio_ops, s, "milkymist-sysctl", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); return 0; }
static void imx_gpt_set_freq(IMXGPTState *s) { uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3); uint32_t freq = imx_clock_frequency(s->ccm, imx_gpt_clocks[clksrc]) / (1 + s->pr); s->freq = freq; DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, freq); if (freq) { ptimer_set_freq(s->timer, freq); } }
static void etsec_realize(DeviceState *dev, Error **errp) { eTSEC *etsec = ETSEC_COMMON(dev); etsec->nic = qemu_new_nic(&net_etsec_info, &etsec->conf, object_get_typename(OBJECT(dev)), dev->id, etsec); qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a); etsec->bh = qemu_bh_new(etsec_timer_hit, etsec); etsec->ptimer = ptimer_init(etsec->bh, PTIMER_POLICY_DEFAULT); ptimer_set_freq(etsec->ptimer, 100); }
static void arm_timer_write(void *opaque, hwaddr offset, uint32_t value) { arm_timer_state *s = (arm_timer_state *)opaque; int freq; switch (offset >> 2) { case 0: /* TimerLoad */ s->limit = value; arm_timer_recalibrate(s, 1); break; case 1: /* TimerValue */ /* ??? Linux seems to want to write to this readonly register. Ignore it. */ break; case 2: /* TimerControl */ if (s->control & TIMER_CTRL_ENABLE) { /* Pause the timer if it is running. This may cause some inaccuracy dure to rounding, but avoids a whole lot of other messyness. */ ptimer_stop(s->timer); } s->control = value; freq = s->freq; /* ??? Need to recalculate expiry time after changing divisor. */ switch ((value >> 2) & 3) { case 1: freq >>= 4; break; case 2: freq >>= 8; break; } arm_timer_recalibrate(s, s->control & TIMER_CTRL_ENABLE); ptimer_set_freq(s->timer, freq); if (s->control & TIMER_CTRL_ENABLE) { /* Restart the timer if still enabled. */ ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0); } break; case 3: /* TimerIntClr */ s->int_level = 0; break; case 6: /* TimerBGLoad */ s->limit = value; arm_timer_recalibrate(s, 0); break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %x\n", __func__, (int)offset); } arm_timer_update(s); }
static int lm32_timer_init(SysBusDevice *dev) { LM32TimerState *s = FROM_SYSBUS(typeof(*s), dev); sysbus_init_irq(dev, &s->irq); s->bh = qemu_bh_new(timer_hit, s); s->ptimer = ptimer_init(s->bh); ptimer_set_freq(s->ptimer, s->freq_hz); memory_region_init_io(&s->iomem, &timer_ops, s, "timer", R_MAX * 4); sysbus_init_mmio(dev, &s->iomem); return 0; }
static void a10_pit_set_freq(AwA10PITState *s, int index) { uint32_t prescaler, source, source_freq; prescaler = 1 << extract32(s->control[index], 4, 3); source = extract32(s->control[index], 2, 2); source_freq = s->clk_freq[source]; if (source_freq) { ptimer_set_freq(s->timer[index], source_freq / prescaler); } else { qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid clock source %u\n", __func__, source); } }
static void digic_timer_init(Object *obj) { DigicTimerState *s = DIGIC_TIMER(obj); s->ptimer = ptimer_init(NULL, PTIMER_POLICY_DEFAULT); /* * FIXME: there is no documentation on Digic timer * frequency setup so let it always run at 1 MHz */ ptimer_set_freq(s->ptimer, 1 * 1000 * 1000); memory_region_init_io(&s->iomem, OBJECT(s), &digic_timer_ops, s, TYPE_DIGIC_TIMER, 0x100); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); }
static void xlx_iom_realize(DeviceState *dev, Error **errp) { XilinxPIT *s = XILINX_IO_MODULE_PIT(dev); unsigned int i; s->prefix = object_get_canonical_path(OBJECT(dev)); for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { RegisterInfo *r = &s->regs_info[i]; *r = (RegisterInfo) { .data = (uint8_t *)&s->regs[i], .data_size = sizeof(uint32_t), .access = &pit_regs_info[i], .debug = XILINX_IO_MODULE_PIT_ERR_DEBUG, .prefix = s->prefix, .opaque = s, }; memory_region_init_io(&r->mem, OBJECT(dev), &iom_pit_ops, r, r->access->name, 4); memory_region_add_subregion(&s->iomem, i * 4, &r->mem); } if (s->cfg.use) { s->bh = qemu_bh_new(pit_timer_hit, s); s->ptimer = ptimer_init(s->bh); ptimer_set_freq(s->ptimer, s->frequency); /* IRQ out to pulse when present timer expires/reloads */ qdev_init_gpio_out(dev, &s->hit_out, 1); /* IRQ in to enable pre-scalar mode. Routed from gpo1 */ qdev_init_gpio_in_named(dev, iom_pit_ps_config, "ps_config", 1); /* hit_out of neighbouring PIT is received as hit_in */ qdev_init_gpio_in_named(dev, iom_pit_ps_hit_in, "ps_hit_in", 1); } } static void xlx_iom_pit_init(Object *obj) { XilinxPIT *s = XILINX_IO_MODULE_PIT(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); memory_region_init_io(&s->iomem, obj, &iom_pit_ops, s, TYPE_XILINX_IO_MODULE_PIT, R_MAX * 4); sysbus_init_mmio(sbd, &s->iomem); sysbus_init_irq(sbd, &s->irq); }
static int lm32_timer_init(SysBusDevice *dev) { LM32TimerState *s = FROM_SYSBUS(typeof(*s), dev); int timer_regs; sysbus_init_irq(dev, &s->irq); s->bh = qemu_bh_new(timer_hit, s); s->ptimer = ptimer_init(s->bh); ptimer_set_freq(s->ptimer, s->freq_hz); timer_regs = cpu_register_io_memory(timer_read_fn, timer_write_fn, s, DEVICE_NATIVE_ENDIAN); sysbus_init_mmio(dev, R_MAX * 4, timer_regs); return 0; }
static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler) { int i = 0; uint32_t value = 0; assert(unit != NULL); if (scaler > 0) { value = unit->freq_hz / (scaler + 1); } else { value = unit->freq_hz; } trace_grlib_gptimer_set_scaler(scaler, value); for (i = 0; i < unit->nr_timers; i++) { ptimer_set_freq(unit->timers[i].ptimer, value); } }
static void mss_timer_init(Object *obj) { MSSTimerState *t = MSS_TIMER(obj); int i; /* Init all the ptimers. */ for (i = 0; i < NUM_TIMERS; i++) { struct Msf2Timer *st = &t->timers[i]; st->bh = qemu_bh_new(timer_hit, st); st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT); ptimer_set_freq(st->ptimer, t->freq_hz); sysbus_init_irq(SYS_BUS_DEVICE(obj), &st->irq); } memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, TYPE_MSS_TIMER, NUM_TIMERS * R_TIM1_MAX * 4); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &t->mmio); }
static int puv3_ost_init(SysBusDevice *dev) { PUV3OSTState *s = FROM_SYSBUS(PUV3OSTState, dev); s->reg_OIER = 0; s->reg_OSSR = 0; s->reg_OSMR0 = 0; s->reg_OSCR = 0; sysbus_init_irq(dev, &s->irq); s->bh = qemu_bh_new(puv3_ost_tick, s); s->ptimer = ptimer_init(s->bh); ptimer_set_freq(s->ptimer, 50 * 1000 * 1000); memory_region_init_io(&s->iomem, &puv3_ost_ops, s, "puv3_ost", PUV3_REGS_OFFSET); sysbus_init_mmio(dev, &s->iomem); return 0; }
static void xilinx_timer_realize(DeviceState *dev, Error **errp) { struct timerblock *t = XILINX_TIMER(dev); unsigned int i; /* Init all the ptimers. */ t->timers = g_malloc0(sizeof t->timers[0] * num_timers(t)); for (i = 0; i < num_timers(t); i++) { struct xlx_timer *xt = &t->timers[i]; xt->parent = t; xt->nr = i; xt->bh = qemu_bh_new(timer_hit, xt); xt->ptimer = ptimer_init(xt->bh); ptimer_set_freq(xt->ptimer, t->freq_hz); } memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer", R_MAX * 4 * num_timers(t)); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &t->mmio); }
static int rtt_init(SysBusDevice *dev) { rtt_state *s = FROM_SYSBUS(rtt_state, dev); QEMUBH *bh; memory_region_init_io(&s->iomem, OBJECT(s), &rtt_ops, s, "rtt", 0x20); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); //s->ssi = ssi_create_bus(&dev->qdev, "ssi"); //rtt_reset(s); //vmstate_register(&dev->qdev, -1, &vmstate_rtt, s); bh = qemu_bh_new(rtt_tick, s); s->timer = ptimer_init(bh); ptimer_set_freq(s->timer, 10); ptimer_set_limit(s->timer, 1, 1); ptimer_run(s->timer, 0); return 0; }
static int puv3_ost_init(SysBusDevice *dev) { PUV3OSTState *s = PUV3_OST(dev); s->reg_OIER = 0; s->reg_OSSR = 0; s->reg_OSMR0 = 0; s->reg_OSCR = 0; sysbus_init_irq(dev, &s->irq); s->bh = qemu_bh_new(puv3_ost_tick, s); s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT); ptimer_set_freq(s->ptimer, 50 * 1000 * 1000); memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost", PUV3_REGS_OFFSET); sysbus_init_mmio(dev, &s->iomem); return 0; }
static int grlib_gptimer_init(SysBusDevice *dev) { GPTimerUnit *unit = FROM_SYSBUS(typeof(*unit), dev); unsigned int i; int timer_regs; assert(unit->nr_timers > 0); assert(unit->nr_timers <= GPTIMER_MAX_TIMERS); unit->timers = qemu_mallocz(sizeof unit->timers[0] * unit->nr_timers); for (i = 0; i < unit->nr_timers; i++) { GPTimer *timer = &unit->timers[i]; timer->unit = unit; timer->bh = qemu_bh_new(grlib_gptimer_hit, timer); timer->ptimer = ptimer_init(timer->bh); timer->id = i; /* One IRQ line for each timer */ sysbus_init_irq(dev, &timer->irq); ptimer_set_freq(timer->ptimer, unit->freq_hz); } timer_regs = cpu_register_io_memory(grlib_gptimer_read, grlib_gptimer_write, unit, DEVICE_NATIVE_ENDIAN); if (timer_regs < 0) { return -1; } sysbus_init_mmio(dev, UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers, timer_regs); return 0; }
static void update_ctrl(struct etrax_timer *t, int tnum) { unsigned int op; unsigned int freq; unsigned int freq_hz; unsigned int div; uint32_t ctrl; ptimer_state *timer; if (tnum == 0) { ctrl = t->rw_tmr0_ctrl; div = t->rw_tmr0_div; timer = t->ptimer_t0; } else { ctrl = t->rw_tmr1_ctrl; div = t->rw_tmr1_div; timer = t->ptimer_t1; } op = ctrl & 3; freq = ctrl >> 2; freq_hz = 32000000; switch (freq) { case 0: case 1: D(printf ("extern or disabled timer clock?\n")); break; case 4: freq_hz = 29493000; break; case 5: freq_hz = 32000000; break; case 6: freq_hz = 32768000; break; case 7: freq_hz = 100000000; break; default: abort(); break; } D(printf ("freq_hz=%d div=%d\n", freq_hz, div)); ptimer_set_freq(timer, freq_hz); ptimer_set_limit(timer, div, 0); switch (op) { case 0: /* Load. */ ptimer_set_limit(timer, div, 1); break; case 1: /* Hold. */ ptimer_stop(timer); break; case 2: /* Run. */ ptimer_run(timer, 0); break; default: abort(); break; } }
static void sh_timer_write(void *opaque, target_phys_addr_t offset, uint32_t value) { sh_timer_state *s = (sh_timer_state *)opaque; int freq; switch (offset >> 2) { case OFFSET_TCOR: s->tcor = value; ptimer_set_limit(s->timer, s->tcor, 0); break; case OFFSET_TCNT: s->tcnt = value; ptimer_set_count(s->timer, s->tcnt); break; case OFFSET_TCR: if (s->enabled) { /* Pause the timer if it is running. This may cause some inaccuracy dure to rounding, but avoids a whole lot of other messyness. */ ptimer_stop(s->timer); } freq = s->freq; /* ??? Need to recalculate expiry time after changing divisor. */ switch (value & TIMER_TCR_TPSC) { case 0: freq >>= 2; break; case 1: freq >>= 4; break; case 2: freq >>= 6; break; case 3: freq >>= 8; break; case 4: freq >>= 10; break; case 6: case 7: if (s->feat & TIMER_FEAT_EXTCLK) break; default: hw_error("sh_timer_write: Reserved TPSC value\n"); break; } switch ((value & TIMER_TCR_CKEG) >> 3) { case 0: break; case 1: case 2: case 3: if (s->feat & TIMER_FEAT_EXTCLK) break; default: hw_error("sh_timer_write: Reserved CKEG value\n"); break; } switch ((value & TIMER_TCR_ICPE) >> 6) { case 0: break; case 2: case 3: if (s->feat & TIMER_FEAT_CAPT) break; default: hw_error("sh_timer_write: Reserved ICPE value\n"); break; } if ((value & TIMER_TCR_UNF) == 0) s->int_level = 0; value &= ~TIMER_TCR_UNF; if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT))) hw_error("sh_timer_write: Reserved ICPF value\n"); value &= ~TIMER_TCR_ICPF; /* capture not supported */ if (value & TIMER_TCR_RESERVED) hw_error("sh_timer_write: Reserved TCR bits set\n"); s->tcr = value; ptimer_set_limit(s->timer, s->tcor, 0); ptimer_set_freq(s->timer, freq); if (s->enabled) { /* Restart the timer if still enabled. */ ptimer_run(s->timer, 0); } break; case OFFSET_TCPR: if (s->feat & TIMER_FEAT_CAPT) { s->tcpr = value; break; } default: hw_error("sh_timer_write: Bad offset %x\n", (int)offset); } sh_timer_update(s); }