Exemplo n.º 1
0
static void main_cpu_reset(void *opaque)
{
    ResetData *s = (ResetData *)opaque;
    CPUState *env = s->env;
    static unsigned int nr_resets;

    cpu_reset(env);
    env->tick_cmpr = TICK_INT_DIS | 0;
    ptimer_set_limit(env->tick, TICK_MAX, 1);
    ptimer_run(env->tick, 1);
    env->stick_cmpr = TICK_INT_DIS | 0;
    ptimer_set_limit(env->stick, TICK_MAX, 1);
    ptimer_run(env->stick, 1);
    env->hstick_cmpr = TICK_INT_DIS | 0;
    ptimer_set_limit(env->hstick, TICK_MAX, 1);
    ptimer_run(env->hstick, 1);
    env->gregs[1] = 0; // Memory start
    env->gregs[2] = ram_size; // Memory size
    env->gregs[3] = 0; // Machine description XXX
    if (nr_resets++ == 0) {
        /* Power on reset */
        env->pc = s->prom_addr + 0x20ULL;
    } else {
        env->pc = s->prom_addr + 0x40ULL;
    }
    env->npc = env->pc + 4;
}
Exemplo n.º 2
0
static void digic_timer_write(void *opaque, hwaddr offset,
                              uint64_t value, unsigned size)
{
    DigicTimerState *s = opaque;

    switch (offset) {
    case DIGIC_TIMER_CONTROL:
        if (value & DIGIC_TIMER_CONTROL_RST) {
            digic_timer_reset((DeviceState *)s);
            break;
        }

        if (value & DIGIC_TIMER_CONTROL_EN) {
            ptimer_run(s->ptimer, 0);
        }

        s->control = (uint32_t)value;
        break;

    case DIGIC_TIMER_RELVALUE:
        s->relvalue = extract32(value, 0, 16);
        ptimer_set_limit(s->ptimer, s->relvalue, 1);
        break;

    case DIGIC_TIMER_VALUE:
        break;

    default:
        qemu_log_mask(LOG_UNIMP,
                      "digic-timer: read access to unknown register 0x"
                      TARGET_FMT_plx, offset);
    }
}
Exemplo n.º 3
0
static void timer_write(void *opaque, target_phys_addr_t addr, uint32_t value)
{
    LM32TimerState *s = opaque;

    trace_lm32_timer_memory_write(addr, value);

    addr >>= 2;
    switch (addr) {
    case R_SR:
        s->regs[R_SR] &= ~SR_TO;
        break;
    case R_CR:
        s->regs[R_CR] = value;
        if (s->regs[R_CR] & CR_START) {
            ptimer_run(s->ptimer, 1);
        }
        if (s->regs[R_CR] & CR_STOP) {
            ptimer_stop(s->ptimer);
        }
        break;
    case R_PERIOD:
        s->regs[R_PERIOD] = value;
        ptimer_set_count(s->ptimer, value);
        break;
    case R_SNAPSHOT:
        error_report("lm32_timer: write access to read only register 0x"
                     TARGET_FMT_plx, addr << 2);
        break;
    default:
        error_report("lm32_timer: write access to unknown register 0x"
                     TARGET_FMT_plx, addr << 2);
        break;
    }
    timer_update_irq(s);
}
Exemplo n.º 4
0
static void imx_epit_reset(DeviceState *dev)
{
    IMXEPITState *s = IMX_EPIT(dev);

    /*
     * Soft reset doesn't touch some bits; hard reset clears them
     */
    s->cr &= (CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN);
    s->sr = 0;
    s->lr = EPIT_TIMER_MAX;
    s->cmp = 0;
    s->cnt = 0;
    /* stop both timers */
    ptimer_stop(s->timer_cmp);
    ptimer_stop(s->timer_reload);
    /* compute new frequency */
    imx_epit_set_freq(s);
    /* init both timers to EPIT_TIMER_MAX */
    ptimer_set_limit(s->timer_cmp, EPIT_TIMER_MAX, 1);
    ptimer_set_limit(s->timer_reload, EPIT_TIMER_MAX, 1);
    if (s->freq && (s->cr & CR_EN)) {
        /* if the timer is still enabled, restart it */
        ptimer_run(s->timer_reload, 0);
    }
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
static void puv3_ost_write(void *opaque, target_phys_addr_t offset,
        uint64_t value, unsigned size)
{
    PUV3OSTState *s = opaque;

    DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
    switch (offset) {
    case 0x00: /* Match Register 0 */
        s->reg_OSMR0 = value;
        if (s->reg_OSMR0 > s->reg_OSCR) {
            ptimer_set_count(s->ptimer, s->reg_OSMR0 - s->reg_OSCR);
        } else {
            ptimer_set_count(s->ptimer, s->reg_OSMR0 +
                    (0xffffffff - s->reg_OSCR));
        }
        ptimer_run(s->ptimer, 2);
        break;
    case 0x14: /* Status Register */
        assert(value == 0);
        if (s->reg_OSSR) {
            s->reg_OSSR = value;
            qemu_irq_lower(s->irq);
        }
        break;
    case 0x1c: /* Interrupt Enable Register */
        s->reg_OIER = value;
        break;
    default:
        DPRINTF("Bad offset %x\n", (int)offset);
    }
}
Exemplo n.º 7
0
static void main_cpu_reset(void *opaque)
{
    ResetData *s = (ResetData *)opaque;
    CPUState *env = s->env;

    cpu_reset(env);
    env->tick_cmpr = TICK_INT_DIS | 0;
    ptimer_set_limit(env->tick, TICK_MAX, 1);
    ptimer_run(env->tick, 1);
    env->stick_cmpr = TICK_INT_DIS | 0;
    ptimer_set_limit(env->stick, TICK_MAX, 1);
    ptimer_run(env->stick, 1);
    env->hstick_cmpr = TICK_INT_DIS | 0;
    ptimer_set_limit(env->hstick, TICK_MAX, 1);
    ptimer_run(env->hstick, 1);
    env->gregs[1] = 0; // Memory start
    env->gregs[2] = ram_size; // Memory size
    env->gregs[3] = 0; // Machine description XXX
    env->pc = s->reset_addr;
    env->npc = env->pc + 4;
}
Exemplo n.º 8
0
static void timer_update(struct Msf2Timer *st)
{
    uint64_t count;

    if (!(st->regs[R_TIM_CTRL] & TIMER_CTRL_ENBL)) {
        ptimer_stop(st->ptimer);
        return;
    }

    count = st->regs[R_TIM_LOADVAL];
    ptimer_set_limit(st->ptimer, count, 1);
    ptimer_run(st->ptimer, 1);
}
Exemplo n.º 9
0
static void timer_hit(void *opaque)
{
    LM32TimerState *s = opaque;

    trace_lm32_timer_hit();

    s->regs[R_SR] |= SR_TO;

    if (s->regs[R_CR] & CR_CONT) {
        ptimer_set_count(s->ptimer, s->regs[R_PERIOD]);
        ptimer_run(s->ptimer, 1);
    }
    timer_update_irq(s);
}
Exemplo n.º 10
0
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);
}
Exemplo n.º 11
0
static void watchdog_hit(void *opaque)
{
    struct etrax_timer *t = opaque;
    if (t->wd_hits == 0) {
        /* real hw gives a single tick before reseting but we are
           a bit friendlier to compensate for our slower execution.  */
        ptimer_set_count(t->ptimer_wd, 10);
        ptimer_run(t->ptimer_wd, 1);
        qemu_irq_raise(t->nmi);
    }
    else
        qemu_system_reset_request();

    t->wd_hits++;
}
Exemplo n.º 12
0
static void etsec_timer_hit(void *opaque)
{
    eTSEC *etsec = opaque;

    ptimer_stop(etsec->ptimer);

    if (!(etsec->regs[DMACTRL].value & DMACTRL_WOP)) {

        if (!(etsec->regs[DMACTRL].value & DMACTRL_GTS)) {
            etsec_walk_tx_ring(etsec, 0);
        }
        ptimer_set_count(etsec->ptimer, 1);
        ptimer_run(etsec->ptimer, 1);
    }
}
Exemplo n.º 13
0
static void timer_enable(struct xlx_timer *xt)
{
    uint64_t count;

    D(fprintf(stderr, "%s timer=%d down=%d\n", __func__,
              xt->nr, xt->regs[R_TCSR] & TCSR_UDT));

    ptimer_stop(xt->ptimer);

    if (xt->regs[R_TCSR] & TCSR_UDT)
        count = xt->regs[R_TLR];
    else
        count = ~0 - xt->regs[R_TLR];
    ptimer_set_limit(xt->ptimer, count, 1);
    ptimer_run(xt->ptimer, 1);
}
Exemplo n.º 14
0
static void imx_gpt_timeout(void *opaque)
{
    IMXGPTState *s = IMX_GPT(opaque);

    DPRINTF("\n");

    s->sr |= s->next_int;
    s->next_int = 0;

    imx_gpt_compute_next_timeout(s, true);

    imx_gpt_update_int(s);

    if (s->freq && (s->cr & GPT_CR_EN)) {
        ptimer_run(s->timer, 1);
    }
}
Exemplo n.º 15
0
static void sh_timer_start_stop(void *opaque, int enable)
{
    sh_timer_state *s = (sh_timer_state *)opaque;

#ifdef DEBUG_TIMER
    printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled);
#endif

    if (s->enabled && !enable) {
        ptimer_stop(s->timer);
    }
    if (!s->enabled && enable) {
        ptimer_run(s->timer, 0);
    }
    s->enabled = !!enable;

#ifdef DEBUG_TIMER
    printf("sh_timer_start_stop done %d\n", s->enabled);
#endif
}
Exemplo n.º 16
0
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;

}
Exemplo n.º 17
0
static void grlib_gptimer_enable(GPTimer *timer)
{
    assert(timer != NULL);


    ptimer_stop(timer->ptimer);

    if (!(timer->config & GPTIMER_ENABLE)) {
        /* Timer disabled */
        trace_grlib_gptimer_disabled(timer->id, timer->config);
        return;
    }

    /* ptimer is triggered when the counter reach 0 but GPTimer is triggered at
       underflow. Set count + 1 to simulate the GPTimer behavior. */

    trace_grlib_gptimer_enable(timer->id, timer->counter + 1);

    ptimer_set_count(timer->ptimer, timer->counter + 1);
    ptimer_run(timer->ptimer, 1);
}
Exemplo n.º 18
0
static void write_dmactrl(eTSEC          *etsec,
                          eTSEC_Register *reg,
                          uint32_t        reg_index,
                          uint32_t        value)
{
    reg->value = value;

    if (value & DMACTRL_GRS) {

        if (etsec->rx_buffer_len != 0) {
            /* Graceful receive stop delayed until end of frame */
        } else {
            /* Graceful receive stop now */
            etsec->regs[IEVENT].value |= IEVENT_GRSC;
            if (etsec->regs[IMASK].value & IMASK_GRSCEN) {
                qemu_irq_raise(etsec->err_irq);
            }
        }
    }

    if (value & DMACTRL_GTS) {

        if (etsec->tx_buffer_len != 0) {
            /* Graceful transmit stop delayed until end of frame */
        } else {
            /* Graceful transmit stop now */
            etsec->regs[IEVENT].value |= IEVENT_GTSC;
            if (etsec->regs[IMASK].value & IMASK_GTSCEN) {
                qemu_irq_raise(etsec->err_irq);
            }
        }
    }

    if (!(value & DMACTRL_WOP)) {
        /* Start polling */
        ptimer_stop(etsec->ptimer);
        ptimer_set_count(etsec->ptimer, 1);
        ptimer_run(etsec->ptimer, 1);
    }
}
Exemplo n.º 19
0
static void pit_control_pw(RegisterInfo *reg, uint64_t value)
{
    XilinxPIT *s = XILINX_IO_MODULE_PIT(reg->opaque);
    uint32_t v32 = value;

    if (!s->cfg.use) {
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Disabled\n", s->prefix);
        return;
    }

    ptimer_stop(s->ptimer);
    if (v32 & IOM_PIT_CONTROL_EN) {
        if (s->ps_enable) {
            /* pre-scalar mode Do-Nothing here. Wait for the friend to hit_in
             * and decrement the counter(s->ps_counter)*/
            s->ps_counter = s->regs[R_IOM_PIT_PRELOAD];
        } else {
            ptimer_set_limit(s->ptimer, s->regs[R_IOM_PIT_PRELOAD], 1);
            ptimer_run(s->ptimer, !(v32 & IOM_PIT_CONTROL_PRELOAD));

        }
    }
}
Exemplo n.º 20
0
static void imx_gpt_reset(DeviceState *dev)
{
    IMXGPTState *s = IMX_GPT(dev);

    /* stop timer */
    ptimer_stop(s->timer);

    /*
     * Soft reset doesn't touch some bits; hard reset clears them
     */
    s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN|
               GPT_CR_WAITEN|GPT_CR_DBGEN);
    s->sr = 0;
    s->pr = 0;
    s->ir = 0;
    s->cnt = 0;
    s->ocr1 = GPT_TIMER_MAX;
    s->ocr2 = GPT_TIMER_MAX;
    s->ocr3 = GPT_TIMER_MAX;
    s->icr1 = 0;
    s->icr2 = 0;

    s->next_timeout = GPT_TIMER_MAX;
    s->next_int = 0;

    /* compute new freq */
    imx_gpt_set_freq(s);

    /* reset the limit to GPT_TIMER_MAX */
    ptimer_set_limit(s->timer, GPT_TIMER_MAX, 1);

    /* if the timer is still enabled, restart it */
    if (s->freq && (s->cr & GPT_CR_EN)) {
        ptimer_run(s->timer, 1);
    }
}
Exemplo n.º 21
0
static void sysctl_write(void *opaque, target_phys_addr_t addr, uint64_t value,
                         unsigned size)
{
    MilkymistSysctlState *s = opaque;

    trace_milkymist_sysctl_memory_write(addr, value);

    addr >>= 2;
    switch (addr) {
    case R_GPIO_OUT:
    case R_GPIO_INTEN:
    case R_TIMER0_COUNTER:
    case R_TIMER1_COUNTER:
        s->regs[addr] = value;
        break;
    case R_TIMER0_COMPARE:
        ptimer_set_limit(s->ptimer0, value, 0);
        s->regs[addr] = value;
        break;
    case R_TIMER1_COMPARE:
        ptimer_set_limit(s->ptimer1, value, 0);
        s->regs[addr] = value;
        break;
    case R_TIMER0_CONTROL:
        s->regs[addr] = value;
        if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) {
            trace_milkymist_sysctl_start_timer0();
            ptimer_set_count(s->ptimer0,
                             s->regs[R_TIMER0_COMPARE] - s->regs[R_TIMER0_COUNTER]);
            ptimer_run(s->ptimer0, 0);
        } else {
            trace_milkymist_sysctl_stop_timer0();
            ptimer_stop(s->ptimer0);
        }
        break;
    case R_TIMER1_CONTROL:
        s->regs[addr] = value;
        if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) {
            trace_milkymist_sysctl_start_timer1();
            ptimer_set_count(s->ptimer1,
                             s->regs[R_TIMER1_COMPARE] - s->regs[R_TIMER1_COUNTER]);
            ptimer_run(s->ptimer1, 0);
        } else {
            trace_milkymist_sysctl_stop_timer1();
            ptimer_stop(s->ptimer1);
        }
        break;
    case R_ICAP:
        sysctl_icap_write(s, value);
        break;
    case R_SYSTEM_ID:
        qemu_system_reset_request();
        break;

    case R_GPIO_IN:
    case R_CAPABILITIES:
        error_report("milkymist_sysctl: write to read-only register 0x"
                     TARGET_FMT_plx, addr << 2);
        break;

    default:
        error_report("milkymist_sysctl: write access to unknown register 0x"
                     TARGET_FMT_plx, addr << 2);
        break;
    }
}
Exemplo n.º 22
0
static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
                                    uint64_t val, unsigned size)
{
    TimerContext *tc = opaque;
    SLAVIO_TIMERState *s = tc->s;
    uint32_t saddr;
    unsigned int timer_index = tc->timer_index;
    CPUTimerState *t = &s->cputimer[timer_index];

    trace_slavio_timer_mem_writel(addr, val);
    saddr = addr >> 2;
    switch (saddr) {
    case TIMER_LIMIT:
        if (slavio_timer_is_user(tc)) {
            uint64_t count;

            // set user counter MSW, reset counter
            t->limit = TIMER_MAX_COUNT64;
            t->counthigh = val & (TIMER_MAX_COUNT64 >> 32);
            t->reached = 0;
            count = ((uint64_t)t->counthigh << 32) | t->count;
            trace_slavio_timer_mem_writel_limit(timer_index, count);
            ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
        } else {
            // set limit, reset counter
            qemu_irq_lower(t->irq);
            t->limit = val & TIMER_MAX_COUNT32;
            if (t->timer) {
                if (t->limit == 0) { /* free-run */
                    ptimer_set_limit(t->timer,
                                     LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
                } else {
                    ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
                }
            }
        }
        break;
    case TIMER_COUNTER:
        if (slavio_timer_is_user(tc)) {
            uint64_t count;

            // set user counter LSW, reset counter
            t->limit = TIMER_MAX_COUNT64;
            t->count = val & TIMER_MAX_COUNT64;
            t->reached = 0;
            count = ((uint64_t)t->counthigh) << 32 | t->count;
            trace_slavio_timer_mem_writel_limit(timer_index, count);
            ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
        } else {
            trace_slavio_timer_mem_writel_counter_invalid();
        }
        break;
    case TIMER_COUNTER_NORST:
        // set limit without resetting counter
        t->limit = val & TIMER_MAX_COUNT32;
        if (t->limit == 0) { /* free-run */
            ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
        } else {
            ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0);
        }
        break;
    case TIMER_STATUS:
        if (slavio_timer_is_user(tc)) {
            // start/stop user counter
            if (val & 1) {
                trace_slavio_timer_mem_writel_status_start(timer_index);
                ptimer_run(t->timer, 0);
            } else {
                trace_slavio_timer_mem_writel_status_stop(timer_index);
                ptimer_stop(t->timer);
            }
        }
        t->run = val & 1;
        break;
    case TIMER_MODE:
        if (timer_index == 0) {
            unsigned int i;

            for (i = 0; i < s->num_cpus; i++) {
                unsigned int processor = 1 << i;
                CPUTimerState *curr_timer = &s->cputimer[i + 1];

                // check for a change in timer mode for this processor
                if ((val & processor) != (s->cputimer_mode & processor)) {
                    if (val & processor) { // counter -> user timer
                        qemu_irq_lower(curr_timer->irq);
                        // counters are always running
                        if (!curr_timer->run) {
                            ptimer_stop(curr_timer->timer);
                        }
                        // user timer limit is always the same
                        curr_timer->limit = TIMER_MAX_COUNT64;
                        ptimer_set_limit(curr_timer->timer,
                                         LIMIT_TO_PERIODS(curr_timer->limit),
                                         1);
                        // set this processors user timer bit in config
                        // register
                        s->cputimer_mode |= processor;
                        trace_slavio_timer_mem_writel_mode_user(timer_index);
                    } else { // user timer -> counter
                        // start the counter
                        ptimer_run(curr_timer->timer, 0);
                        // clear this processors user timer bit in config
                        // register
                        s->cputimer_mode &= ~processor;
                        trace_slavio_timer_mem_writel_mode_counter(timer_index);
                    }
                }
            }
        } else {
            trace_slavio_timer_mem_writel_mode_invalid();
        }
        break;
    default:
        trace_slavio_timer_mem_writel_invalid(addr);
        break;
    }
Exemplo n.º 23
0
static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
                          unsigned size)
{
    IMXGPTState *s = IMX_GPT(opaque);
    uint32_t oldreg;
    uint32_t reg = offset >> 2;

    DPRINTF("(%s, value = 0x%08x)\n", imx_gpt_reg_name(reg),
            (uint32_t)value);

    switch (reg) {
    case 0:
        oldreg = s->cr;
        s->cr = value & ~0x7c14;
        if (s->cr & GPT_CR_SWR) { /* force reset */
            /* handle the reset */
            imx_gpt_reset(DEVICE(s));
        } else {
            /* set our freq, as the source might have changed */
            imx_gpt_set_freq(s);

            if ((oldreg ^ s->cr) & GPT_CR_EN) {
                if (s->cr & GPT_CR_EN) {
                    if (s->cr & GPT_CR_ENMOD) {
                        s->next_timeout = GPT_TIMER_MAX;
                        ptimer_set_count(s->timer, GPT_TIMER_MAX);
                        imx_gpt_compute_next_timeout(s, false);
                    }
                    ptimer_run(s->timer, 1);
                } else {
                    /* stop timer */
                    ptimer_stop(s->timer);
                }
            }
        }
        break;

    case 1: /* Prescaler */
        s->pr = value & 0xfff;
        imx_gpt_set_freq(s);
        break;

    case 2: /* SR */
        s->sr &= ~(value & 0x3f);
        imx_gpt_update_int(s);
        break;

    case 3: /* IR -- interrupt register */
        s->ir = value & 0x3f;
        imx_gpt_update_int(s);

        imx_gpt_compute_next_timeout(s, false);

        break;

    case 4: /* OCR1 -- output compare register */
        s->ocr1 = value;

        /* In non-freerun mode, reset count when this register is written */
        if (!(s->cr & GPT_CR_FRR)) {
            s->next_timeout = GPT_TIMER_MAX;
            ptimer_set_limit(s->timer, GPT_TIMER_MAX, 1);
        }

        /* compute the new timeout */
        imx_gpt_compute_next_timeout(s, false);

        break;

    case 5: /* OCR2 -- output compare register */
        s->ocr2 = value;

        /* compute the new timeout */
        imx_gpt_compute_next_timeout(s, false);

        break;

    case 6: /* OCR3 -- output compare register */
        s->ocr3 = value;

        /* compute the new timeout */
        imx_gpt_compute_next_timeout(s, false);

        break;

    default:
        IPRINTF("Bad offset %x\n", reg);
        break;
    }
}
Exemplo n.º 24
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;
    }
}
Exemplo n.º 25
0
static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
                            unsigned size)
{
     AwA10PITState *s = AW_A10_PIT(opaque);
     uint8_t index;

    switch (offset) {
    case AW_A10_PIT_TIMER_IRQ_EN:
        s->irq_enable = value;
        a10_pit_update_irq(s);
        break;
    case AW_A10_PIT_TIMER_IRQ_ST:
        s->irq_status &= ~value;
        a10_pit_update_irq(s);
        break;
    case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE_END:
        index = offset & 0xf0;
        index >>= 4;
        index -= 1;
        switch (offset & 0x0f) {
        case AW_A10_PIT_TIMER_CONTROL:
            s->control[index] = value;
            a10_pit_set_freq(s, index);
            if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
                ptimer_set_count(s->timer[index], s->interval[index]);
            }
            if (s->control[index] & AW_A10_PIT_TIMER_EN) {
                int oneshot = 0;
                if (s->control[index] & AW_A10_PIT_TIMER_MODE) {
                    oneshot = 1;
                }
                ptimer_run(s->timer[index], oneshot);
            } else {
                ptimer_stop(s->timer[index]);
            }
            break;
        case AW_A10_PIT_TIMER_INTERVAL:
            s->interval[index] = value;
            ptimer_set_limit(s->timer[index], s->interval[index], 1);
            break;
        case AW_A10_PIT_TIMER_COUNT:
            s->count[index] = value;
            break;
        default:
            qemu_log_mask(LOG_GUEST_ERROR,
                          "%s: Bad offset 0x%x\n",  __func__, (int)offset);
        }
        break;
    case AW_A10_PIT_WDOG_CONTROL:
        s->watch_dog_control = value;
        break;
    case AW_A10_PIT_WDOG_MODE:
        s->watch_dog_mode = value;
        break;
    case AW_A10_PIT_COUNT_LO:
        s->count_lo = value;
        break;
    case AW_A10_PIT_COUNT_HI:
        s->count_hi = value;
        break;
    case AW_A10_PIT_COUNT_CTL:
        s->count_ctl = value;
        if (s->count_ctl & AW_A10_PIT_COUNT_RL_EN) {
            uint64_t  tmp_count = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);

            s->count_lo = tmp_count;
            s->count_hi = tmp_count >> 32;
            s->count_ctl &= ~AW_A10_PIT_COUNT_RL_EN;
        }
        if (s->count_ctl & AW_A10_PIT_COUNT_CLR_EN) {
            s->count_lo = 0;
            s->count_hi = 0;
            s->count_ctl &= ~AW_A10_PIT_COUNT_CLR_EN;
        }
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
        break;
    }
Exemplo n.º 26
0
static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
                                    uint32_t val)
{
    TimerContext *tc = opaque;
    SLAVIO_TIMERState *s = tc->s;
    uint32_t saddr;
    unsigned int timer_index = tc->timer_index;
    CPUTimerState *t = &s->cputimer[timer_index];

    DPRINTF("write " TARGET_FMT_plx " %08x\n", addr, val);
    saddr = addr >> 2;
    switch (saddr) {
    case TIMER_LIMIT:
        if (slavio_timer_is_user(tc)) {
            uint64_t count;

            // set user counter MSW, reset counter
            t->limit = TIMER_MAX_COUNT64;
            t->counthigh = val & (TIMER_MAX_COUNT64 >> 32);
            t->reached = 0;
            count = ((uint64_t)t->counthigh << 32) | t->count;
            DPRINTF("processor %d user timer set to %016" PRIx64 "\n",
                    timer_index, count);
            ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
        } else {
            // set limit, reset counter
            qemu_irq_lower(t->irq);
            t->limit = val & TIMER_MAX_COUNT32;
            if (t->timer) {
                if (t->limit == 0) { /* free-run */
                    ptimer_set_limit(t->timer,
                                     LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
                } else {
                    ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
                }
            }
        }
        break;
    case TIMER_COUNTER:
        if (slavio_timer_is_user(tc)) {
            uint64_t count;

            // set user counter LSW, reset counter
            t->limit = TIMER_MAX_COUNT64;
            t->count = val & TIMER_MAX_COUNT64;
            t->reached = 0;
            count = ((uint64_t)t->counthigh) << 32 | t->count;
            DPRINTF("processor %d user timer set to %016" PRIx64 "\n",
                    timer_index, count);
            ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
        } else
            DPRINTF("not user timer\n");
        break;
    case TIMER_COUNTER_NORST:
        // set limit without resetting counter
        t->limit = val & TIMER_MAX_COUNT32;
        if (t->limit == 0) { /* free-run */
            ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
        } else {
            ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0);
        }
        break;
    case TIMER_STATUS:
        if (slavio_timer_is_user(tc)) {
            // start/stop user counter
            if ((val & 1) && !t->running) {
                DPRINTF("processor %d user timer started\n",
                        timer_index);
                ptimer_run(t->timer, 0);
                t->running = 1;
            } else if (!(val & 1) && t->running) {
                DPRINTF("processor %d user timer stopped\n",
                        timer_index);
                ptimer_stop(t->timer);
                t->running = 0;
            }
        }
        break;
    case TIMER_MODE:
        if (timer_index == 0) {
            unsigned int i;

            for (i = 0; i < s->num_cpus; i++) {
                unsigned int processor = 1 << i;
                CPUTimerState *curr_timer = &s->cputimer[i + 1];

                // check for a change in timer mode for this processor
                if ((val & processor) != (s->cputimer_mode & processor)) {
                    if (val & processor) { // counter -> user timer
                        qemu_irq_lower(curr_timer->irq);
                        // counters are always running
                        ptimer_stop(curr_timer->timer);
                        curr_timer->running = 0;
                        // user timer limit is always the same
                        curr_timer->limit = TIMER_MAX_COUNT64;
                        ptimer_set_limit(curr_timer->timer,
                                         LIMIT_TO_PERIODS(curr_timer->limit),
                                         1);
                        // set this processors user timer bit in config
                        // register
                        s->cputimer_mode |= processor;
                        DPRINTF("processor %d changed from counter to user "
                                "timer\n", timer_index);
                    } else { // user timer -> counter
                        // stop the user timer if it is running
                        if (curr_timer->running) {
                            ptimer_stop(curr_timer->timer);
                        }
                        // start the counter
                        ptimer_run(curr_timer->timer, 0);
                        curr_timer->running = 1;
                        // clear this processors user timer bit in config
                        // register
                        s->cputimer_mode &= ~processor;
                        DPRINTF("processor %d changed from user timer to "
                                "counter\n", timer_index);
                    }
                }
            }
        } else {
            DPRINTF("not system timer\n");
        }
        break;
    default:
        DPRINTF("invalid write address " TARGET_FMT_plx "\n", addr);
        break;
    }
Exemplo n.º 27
0
static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
                           unsigned size)
{
    IMXEPITState *s = IMX_EPIT(opaque);
    uint32_t reg = offset >> 2;
    uint64_t oldcr;

    DPRINTF("(%s, value = 0x%08x)\n", imx_epit_reg_name(reg), (uint32_t)value);

    switch (reg) {
    case 0: /* CR */

        oldcr = s->cr;
        s->cr = value & 0x03ffffff;
        if (s->cr & CR_SWR) {
            /* handle the reset */
            imx_epit_reset(DEVICE(s));
        } else {
            imx_epit_set_freq(s);
        }

        if (s->freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) {
            if (s->cr & CR_ENMOD) {
                if (s->cr & CR_RLD) {
                    ptimer_set_limit(s->timer_reload, s->lr, 1);
                    ptimer_set_limit(s->timer_cmp, s->lr, 1);
                } else {
                    ptimer_set_limit(s->timer_reload, EPIT_TIMER_MAX, 1);
                    ptimer_set_limit(s->timer_cmp, EPIT_TIMER_MAX, 1);
                }
            }

            imx_epit_reload_compare_timer(s);
            ptimer_run(s->timer_reload, 0);
            if (s->cr & CR_OCIEN) {
                ptimer_run(s->timer_cmp, 0);
            } else {
                ptimer_stop(s->timer_cmp);
            }
        } else if (!(s->cr & CR_EN)) {
            /* stop both timers */
            ptimer_stop(s->timer_reload);
            ptimer_stop(s->timer_cmp);
        } else  if (s->cr & CR_OCIEN) {
            if (!(oldcr & CR_OCIEN)) {
                imx_epit_reload_compare_timer(s);
                ptimer_run(s->timer_cmp, 0);
            }
        } else {
            ptimer_stop(s->timer_cmp);
        }
        break;

    case 1: /* SR - ACK*/
        /* writing 1 to OCIF clear the OCIF bit */
        if (value & 0x01) {
            s->sr = 0;
            imx_epit_update_int(s);
        }
        break;

    case 2: /* LR - set ticks */
        s->lr = value;

        if (s->cr & CR_RLD) {
            /* Also set the limit if the LRD bit is set */
            /* If IOVW bit is set then set the timer value */
            ptimer_set_limit(s->timer_reload, s->lr, s->cr & CR_IOVW);
            ptimer_set_limit(s->timer_cmp, s->lr, 0);
        } else if (s->cr & CR_IOVW) {
            /* If IOVW bit is set then set the timer value */
            ptimer_set_count(s->timer_reload, s->lr);
        }

        imx_epit_reload_compare_timer(s);
        break;

    case 3: /* CMP */
        s->cmp = value;

        imx_epit_reload_compare_timer(s);

        break;

    default:
        IPRINTF("Bad offset %x\n", reg);

        break;
    }
}
Exemplo n.º 28
0
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);
}