Exemplo n.º 1
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.º 2
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.º 3
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);
    }
}
Exemplo n.º 4
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.º 5
0
static void lan9118_reset(DeviceState *d)
{
    lan9118_state *s = LAN9118(d);

    s->irq_cfg &= (IRQ_TYPE | IRQ_POL);
    s->int_sts = 0;
    s->int_en = 0;
    s->fifo_int = 0x48000000;
    s->rx_cfg = 0;
    s->tx_cfg = 0;
    s->hw_cfg = s->mode_16bit ? 0x00050000 : 0x00050004;
    s->pmt_ctrl &= 0x45;
    s->gpio_cfg = 0;
    s->txp->fifo_used = 0;
    s->txp->state = TX_IDLE;
    s->txp->cmd_a = 0xffffffffu;
    s->txp->cmd_b = 0xffffffffu;
    s->txp->len = 0;
    s->txp->fifo_used = 0;
    s->tx_fifo_size = 4608;
    s->tx_status_fifo_used = 0;
    s->rx_status_fifo_size = 704;
    s->rx_fifo_size = 2640;
    s->rx_fifo_used = 0;
    s->rx_status_fifo_size = 176;
    s->rx_status_fifo_used = 0;
    s->rxp_offset = 0;
    s->rxp_size = 0;
    s->rxp_pad = 0;
    s->rx_packet_size_tail = s->rx_packet_size_head;
    s->rx_packet_size[s->rx_packet_size_head] = 0;
    s->mac_cmd = 0;
    s->mac_data = 0;
    s->afc_cfg = 0;
    s->e2p_cmd = 0;
    s->e2p_data = 0;
    s->free_timer_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 40;

    ptimer_stop(s->timer);
    ptimer_set_count(s->timer, 0xffff);
    s->gpt_cfg = 0xffff;

    s->mac_cr = MAC_CR_PRMS;
    s->mac_hashh = 0;
    s->mac_hashl = 0;
    s->mac_mii_acc = 0;
    s->mac_mii_data = 0;
    s->mac_flow = 0;

    s->read_word_n = 0;
    s->write_word_n = 0;

    phy_reset(s);

    s->eeprom_writable = 0;
    lan9118_reload_eeprom(s);
}
Exemplo n.º 6
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.º 7
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.º 8
0
static void imx_epit_reload_compare_timer(IMXEPITState *s)
{
    if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN))  {
        /* if the compare feature is on and timers are running */
        uint32_t tmp = imx_epit_update_count(s);
        uint64_t next;
        if (tmp > s->cmp) {
            /* It'll fire in this round of the timer */
            next = tmp - s->cmp;
        } else { /* catch it next time around */
            next = tmp - s->cmp + ((s->cr & CR_RLD) ? EPIT_TIMER_MAX : s->lr);
        }
        ptimer_set_count(s->timer_cmp, next);
    }
}
Exemplo n.º 9
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.º 10
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.º 11
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.º 12
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.º 13
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.º 14
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);
}
Exemplo n.º 15
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.º 16
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.º 17
0
void cpu_tick_set_count(void *opaque, uint64_t count)
{
    ptimer_set_count(opaque, -count);
}
Exemplo n.º 18
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.º 19
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;
    }
}