Beispiel #1
0
void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
                             void *vfpst, uint32_t desc)
{
    uintptr_t opr_sz = simd_oprsz(desc);
    float32 *d = vd;
    float32 *n = vn;
    float32 *m = vm;
    float_status *fpst = vfpst;
    intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
    uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
    uint32_t neg_real = flip ^ neg_imag;
    uintptr_t i;
    float32 e1 = m[H4(flip)];
    float32 e3 = m[H4(1 - flip)];

    /* Shift boolean to the sign bit so we can xor to negate.  */
    neg_real <<= 31;
    neg_imag <<= 31;
    e1 ^= neg_real;
    e3 ^= neg_imag;

    for (i = 0; i < opr_sz / 4; i += 2) {
        float32 e2 = n[H4(i + flip)];
        float32 e4 = e2;

        d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
        d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
    }
    clear_tail(d, opr_sz, simd_maxsz(desc));
}
static void data_handler(void *opaque, int irq, int level, int channel)
{
    XlnxAXIGPIO *s = XLNX_AXI_GPIO(opaque);
    unsigned int data_regnr, tri_regnr;

    assert(channel > 0 && channel < 3);
    data_regnr = channel == 1 ? R_GPIO_DATA : R_GPIO2_DATA;
    tri_regnr = channel == 1 ? R_GPIO_TRI : R_GPIO2_TRI;

    if (!extract32(s->regs[tri_regnr], irq, 1) ||
        extract32(s->regs[data_regnr], irq, 1) == level) {
        /* GPIO is configured as output, or there is no change */
        return;
    }

    s->regs[data_regnr] = deposit32(s->regs[data_regnr], irq, 1, level);

    switch (channel) {
    case 1:
        DEP_AF_DP32(s->regs, IP_ISR, CHANNEL1_ST, 1);
        break;
    case 2:
        DEP_AF_DP32(s->regs, IP_ISR, CHANNEL2_ST, 1);
        break;
    }

    irq_update(s);
}
Beispiel #3
0
static void imx_gpio_set_int_line(IMXGPIOState *s, int line, IMXGPIOLevel level)
{
    /* if this signal isn't configured as an input signal, nothing to do */
    if (!extract32(s->gdir, line, 1)) {
        return;
    }

    /* When set, EDGE_SEL overrides the ICR config */
    if (extract32(s->edge_sel, line, 1)) {
        /* we detect interrupt on rising and falling edge */
        if (extract32(s->psr, line, 1) != level) {
            /* level changed */
            s->isr = deposit32(s->isr, line, 1, 1);
        }
    } else if (extract64(s->icr, 2*line + 1, 1)) {
        /* interrupt is edge sensitive */
        if (extract32(s->psr, line, 1) != level) {
            /* level changed */
            if (extract64(s->icr, 2*line, 1) != level) {
                s->isr = deposit32(s->isr, line, 1, 1);
            }
        }
    } else {
        /* interrupt is level sensitive */
        if (extract64(s->icr, 2*line, 1) == level) {
            s->isr = deposit32(s->isr, line, 1, 1);
        }
    }
}
Beispiel #4
0
static void decode_fast_read_cmd(Flash *s)
{
    s->needed_bytes = get_addr_length(s);
    switch (get_man(s)) {
    /* Dummy cycles - modeled with bytes writes instead of bits */
    case MAN_WINBOND:
        s->needed_bytes += 8;
        break;
    case MAN_NUMONYX:
        s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
        break;
    case MAN_MACRONIX:
        if (extract32(s->volatile_cfg, 6, 2) == 1) {
            s->needed_bytes += 6;
        } else {
            s->needed_bytes += 8;
        }
        break;
    case MAN_SPANSION:
        s->needed_bytes += extract32(s->spansion_cr2v,
                                    SPANSION_DUMMY_CLK_POS,
                                    SPANSION_DUMMY_CLK_LEN
                                    );
        break;
    default:
        break;
    }
    s->pos = 0;
    s->len = 0;
    s->state = STATE_COLLECTING_DATA;
}
Beispiel #5
0
static void bcm2835_ic_write(void *opaque, hwaddr offset, uint64_t val,
                             unsigned size)
{
    BCM2835ICState *s = opaque;

    switch (offset) {
    case FIQ_CONTROL:
        s->fiq_select = extract32(val, 0, 7);
        s->fiq_enable = extract32(val, 7, 1);
        break;
    case IRQ_ENABLE_1:
        s->gpu_irq_enable |= val;
        break;
    case IRQ_ENABLE_2:
        s->gpu_irq_enable |= val << 32;
        break;
    case IRQ_ENABLE_BASIC:
        s->arm_irq_enable |= val & 0xff;
        break;
    case IRQ_DISABLE_1:
        s->gpu_irq_enable &= ~val;
        break;
    case IRQ_DISABLE_2:
        s->gpu_irq_enable &= ~(val << 32);
        break;
    case IRQ_DISABLE_BASIC:
        s->arm_irq_enable &= ~val & 0xff;
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
                      __func__, offset);
        return;
    }
    bcm2835_ic_update(s);
}
static void xlnx_axi_gpio_data_post_write(XlnxAXIGPIO *s, uint64_t val,
                                          int channel)
{
    unsigned int tri_regnr;
    bool gpio_set;
    int i;

    assert(channel > 0 && channel < 3);
    tri_regnr = channel == 1 ? R_GPIO_TRI : R_GPIO2_TRI;

    for (i = 0; i < 32; i++) {
        if (extract32(s->regs[tri_regnr], i, 1)) {
            /* GPIO is configured as input, don't change anything */
            continue;
        }

        gpio_set = extract32(val, i, 1);

        switch (channel) {
        case 1:
            qemu_set_irq(s->outputs1[i], gpio_set);
            break;
        case 2:
            qemu_set_irq(s->outputs2[i], gpio_set);
            break;
        }
    }
}
Beispiel #7
0
void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
                         void *vfpst, uint32_t desc)
{
    uintptr_t opr_sz = simd_oprsz(desc);
    float64 *d = vd;
    float64 *n = vn;
    float64 *m = vm;
    float_status *fpst = vfpst;
    intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
    uint64_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
    uint64_t neg_real = flip ^ neg_imag;
    uintptr_t i;

    /* Shift boolean to the sign bit so we can xor to negate.  */
    neg_real <<= 63;
    neg_imag <<= 63;

    for (i = 0; i < opr_sz / 8; i += 2) {
        float64 e2 = n[i + flip];
        float64 e1 = m[i + flip] ^ neg_real;
        float64 e4 = e2;
        float64 e3 = m[i + 1 - flip] ^ neg_imag;

        d[i] = float64_muladd(e2, e1, d[i], 0, fpst);
        d[i + 1] = float64_muladd(e4, e3, d[i + 1], 0, fpst);
    }
    clear_tail(d, opr_sz, simd_maxsz(desc));
}
Beispiel #8
0
/*
 * The state machine needs some refinement. It is only used to track
 * invalid STOP commands for the moment.
 */
static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
{
    bus->cmd &= ~0xFFFF;
    bus->cmd |= value & 0xFFFF;

    if (bus->cmd & I2CD_M_START_CMD) {
        uint8_t state = aspeed_i2c_get_state(bus) & I2CD_MACTIVE ?
            I2CD_MSTARTR : I2CD_MSTART;

        aspeed_i2c_set_state(bus, state);

        if (i2c_start_transfer(bus->bus, extract32(bus->buf, 1, 7),
                               extract32(bus->buf, 0, 1))) {
            bus->intr_status |= I2CD_INTR_TX_NAK;
        } else {
            bus->intr_status |= I2CD_INTR_TX_ACK;
        }

        /* START command is also a TX command, as the slave address is
         * sent on the bus */
        bus->cmd &= ~(I2CD_M_START_CMD | I2CD_M_TX_CMD);

        /* No slave found */
        if (!i2c_bus_busy(bus->bus)) {
            return;
        }
        aspeed_i2c_set_state(bus, I2CD_MACTIVE);
    }

    if (bus->cmd & I2CD_M_TX_CMD) {
        aspeed_i2c_set_state(bus, I2CD_MTXD);
        if (i2c_send(bus->bus, bus->buf)) {
            bus->intr_status |= (I2CD_INTR_TX_NAK);
            i2c_end_transfer(bus->bus);
        } else {
            bus->intr_status |= I2CD_INTR_TX_ACK;
        }
        bus->cmd &= ~I2CD_M_TX_CMD;
        aspeed_i2c_set_state(bus, I2CD_MACTIVE);
    }

    if ((bus->cmd & (I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST)) &&
        !(bus->intr_status & I2CD_INTR_RX_DONE)) {
        aspeed_i2c_handle_rx_cmd(bus);
    }

    if (bus->cmd & I2CD_M_STOP_CMD) {
        if (!(aspeed_i2c_get_state(bus) & I2CD_MACTIVE)) {
            qemu_log_mask(LOG_GUEST_ERROR, "%s: abnormal stop\n", __func__);
            bus->intr_status |= I2CD_INTR_ABNORMAL;
        } else {
            aspeed_i2c_set_state(bus, I2CD_MSTOP);
            i2c_end_transfer(bus->bus);
            bus->intr_status |= I2CD_INTR_NORMAL_STOP;
        }
        bus->cmd &= ~I2CD_M_STOP_CMD;
        aspeed_i2c_set_state(bus, I2CD_IDLE);
    }
}
Beispiel #9
0
static void stm32_rcc_RCC_PLLCFGR_write(Stm32Rcc *s, uint32_t new_value, bool init)
{
    uint32_t new_PLLSRC, new_PLLP, new_PLLN, new_PLLM;
    /* PLLSRC */
    new_PLLSRC = extract32(new_value, RCC_PLLCFGR_PLLSRC_BIT, 1);
    if(!init) {
        if(clktree_is_enabled(s->PLLCLK) &&
           (new_PLLSRC != s->RCC_PLLCFGR_PLLSRC)) {
            stm32_hw_warn("Can only change PLLSRC while PLL is disabled");
        }
    }
    clktree_set_selected_input(s->PLLCLK, new_PLLSRC);
    s->RCC_PLLCFGR_PLLSRC = new_PLLSRC;

    new_PLLP = extract32(new_value,
                           RCC_PLLCFGR_PLLP_START,
                           RCC_PLLCFGR_PLLP_LENGTH);
    if(!init) {
          if(clktree_is_enabled(s->PLLCLK) &&
           (new_PLLP != s->RCC_PLLCFGR_PLLP)) {
               stm32_hw_warn("Can only change PLLP while PLL is disabled");
          }
    }
    assert(new_PLLP <= 0xf);
    clktree_set_scale(s->PLLCLK, 1, 2 + 2 * new_PLLP);

    s->RCC_PLLCFGR_PLLP = new_PLLP;

    new_PLLM = extract32(new_value,
                           RCC_PLLCFGR_PLLM_START,
                           RCC_PLLCFGR_PLLM_LENGTH);
    new_PLLN = extract32(new_value,
                           RCC_PLLCFGR_PLLN_START,
                           RCC_PLLCFGR_PLLN_LENGTH);

    if(!init) {
          if(clktree_is_enabled(s->PLLCLK) &&
           (new_PLLM != s->RCC_PLLCFGR_PLLM || new_PLLN != s->RCC_PLLCFGR_PLLN)) {
               stm32_hw_warn("Can only change PLLM/N while PLL is disabled");
          }
    }
    if(new_PLLN < 64 || new_PLLN > 432 ||
       new_PLLM < 2) {
       stm32_hw_warn("Invalid PLLM (%u) or PLLN (%u) set", new_PLLM, new_PLLN);
    } else {
        clktree_set_scale(s->PLL_VCO, new_PLLN, new_PLLM);
    }


    s->RCC_PLLCFGR_PLLM = new_PLLM;
    s->RCC_PLLCFGR_PLLN = new_PLLN;
    DPRINT("PLLP=%u, PLLM=%u, PLLN=%u\n", new_PLLP, new_PLLM, new_PLLN);
}
Beispiel #10
0
static inline void imx_gpio_set_all_output_lines(IMXGPIOState *s)
{
    int i;

    for (i = 0; i < IMX_GPIO_PIN_COUNT; i++) {
        /*
         * if the line is set as output, then forward the line
         * level to its user.
         */
        if (extract32(s->gdir, i, 1) && s->output[i]) {
            qemu_set_irq(s->output[i], extract32(s->dr, i, 1));
        }
    }
}
Beispiel #11
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);
    }
}
Beispiel #12
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);
    }
}
Beispiel #13
0
inline void
extract(const std::vector<unsigned char> &vec, size_t &offset,
	unsigned &target)
{
  target = extract32(vec, offset);
  offset += 4;
}
Beispiel #14
0
/* Read a register group from the kernel VGIC */
static void kvm_dist_get(GICState *s, uint32_t offset, int width,
                         int maxirq, vgic_translate_fn translate_fn)
{
    uint32_t reg;
    int i;
    int j;
    int irq;
    int cpu;
    int regsz = 32 / width; /* irqs per kernel register */
    uint32_t field;

    for_each_irq_reg(i, maxirq, width) {
        irq = i * regsz;
        cpu = 0;
        while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
            kvm_gicd_access(s, offset, cpu, &reg, false);
            for (j = 0; j < regsz; j++) {
                field = extract32(reg, j * width, width);
                translate_fn(s, irq + j, cpu, &field, false);
            }

            cpu++;
        }
        offset += 4;
    }
Beispiel #15
0
void HELPER(gvec_fcadds)(void *vd, void *vn, void *vm,
                         void *vfpst, uint32_t desc)
{
    uintptr_t opr_sz = simd_oprsz(desc);
    float32 *d = vd;
    float32 *n = vn;
    float32 *m = vm;
    float_status *fpst = vfpst;
    uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
    uint32_t neg_imag = neg_real ^ 1;
    uintptr_t i;

    /* Shift boolean to the sign bit so we can xor to negate.  */
    neg_real <<= 31;
    neg_imag <<= 31;

    for (i = 0; i < opr_sz / 4; i += 2) {
        float32 e0 = n[H4(i)];
        float32 e1 = m[H4(i + 1)] ^ neg_imag;
        float32 e2 = n[H4(i + 1)];
        float32 e3 = m[H4(i)] ^ neg_real;

        d[H4(i)] = float32_add(e0, e1, fpst);
        d[H4(i + 1)] = float32_add(e2, e3, fpst);
    }
    clear_tail(d, opr_sz, simd_maxsz(desc));
}
Beispiel #16
0
static uint32_t lookup_bte32(CPUX86State *env, uint32_t base, uintptr_t ra)
{
    uint32_t bndcsr, bde, bt;

    if ((env->hflags & HF_CPL_MASK) == 3) {
        bndcsr = env->bndcs_regs.cfgu;
    } else {
        bndcsr = env->msr_bndcfgs;
    }

    bde = (extract32(base, 12, 20) << 2) + (bndcsr & TARGET_PAGE_MASK);
    bt = cpu_ldl_data_ra(env, bde, ra);
    if ((bt & 1) == 0) {
        env->bndcs_regs.sts = bde | 2;
        raise_exception_ra(env, EXCP05_BOUND, ra);
    }

    return (extract32(base, 2, 10) << 4) + (bt & ~3);
}
Beispiel #17
0
static void imx_gpio_set_all_int_lines(IMXGPIOState *s)
{
    int i;

    for (i = 0; i < IMX_GPIO_PIN_COUNT; i++) {
        IMXGPIOLevel imx_level = extract32(s->psr, i, 1);
        imx_gpio_set_int_line(s, i, imx_level);
    }

    imx_gpio_update_int(s);
}
Beispiel #18
0
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);
    }
}
Beispiel #19
0
static void decode_qio_read_cmd(Flash *s)
{
    s->needed_bytes = get_addr_length(s);
    /* Dummy cycles modeled with bytes writes instead of bits */
    switch (get_man(s)) {
    case MAN_WINBOND:
        s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
        s->needed_bytes += 4;
        break;
    case MAN_SPANSION:
        s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
        s->needed_bytes += extract32(s->spansion_cr2v,
                                    SPANSION_DUMMY_CLK_POS,
                                    SPANSION_DUMMY_CLK_LEN
                                    );
        break;
    case MAN_NUMONYX:
        s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
        break;
    case MAN_MACRONIX:
        switch (extract32(s->volatile_cfg, 6, 2)) {
        case 1:
            s->needed_bytes += 4;
            break;
        case 2:
            s->needed_bytes += 8;
            break;
        default:
            s->needed_bytes += 6;
            break;
        }
        break;
    default:
        break;
    }
    s->pos = 0;
    s->len = 0;
    s->state = STATE_COLLECTING_DATA;
}
Beispiel #20
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);
    }
}
Beispiel #21
0
static void zynq_xadc_update_ints(ZynqXADCState *s)
{

    /* We are fast, commands are actioned instantly so the CFIFO is always
     * empty (and below threshold).
     */
    s->regs[INT_STS] |= INT_CFIFO_LTH;

    if (s->xadc_dfifo_entries >
        extract32(s->regs[CFG], CFG_DFIFOTH_SHIFT, CFG_DFIFOTH_LENGTH)) {
        s->regs[INT_STS] |= INT_DFIFO_GTH;
    }

    qemu_set_irq(s->qemu_irq, !!(s->regs[INT_STS] & ~s->regs[INT_MASK]));
}
Beispiel #22
0
static uint32_t pmc_get_sss_regfield(SSSBase *p, int remote)
{
    PMCSSS *s = PMC_SSS(p);
    uint32_t reg;
    uint32_t indx;

    reg = extract32(s->regs[R_CFG], r_pmc_cfg_sss_shifts[remote],
                      R_PMC_SSS_FIELD_LENGTH);
    for (indx = 0; indx < PMC_NUM_REMOTES; indx++) {
        if (reg == pmc_sss_cfg_mapping[remote][indx]) {
            break;
        }
    }
    /* indx == PMC_NUM_REMOTES indicates invalid SSS channel
     * and its handled by sss-base device
     */

    return indx;
}
Beispiel #23
0
/* Update interrupts.  */
static void bcm2835_ic_update(BCM2835ICState *s)
{
    bool set = false;

    if (s->fiq_enable) {
        if (s->fiq_select >= GPU_IRQS) {
            /* ARM IRQ */
            set = extract32(s->arm_irq_level, s->fiq_select - GPU_IRQS, 1);
        } else {
            set = extract64(s->gpu_irq_level, s->fiq_select, 1);
        }
    }
    qemu_set_irq(s->fiq, set);

    set = (s->gpu_irq_level & s->gpu_irq_enable)
        || (s->arm_irq_level & s->arm_irq_enable);
    qemu_set_irq(s->irq, set);

}
Beispiel #24
0
/*
 * ACPI 1.0b: 6.4.3.4 32-Bit Fixed Location Memory Range Descriptor
 * (Type 1, Large Item Name 0x6)
 */
Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
                        AmlReadAndWrite read_and_write)
{
    Aml *var = aml_alloc();
    build_append_byte(var->buf, 0x86); /* Memory32Fixed Resource Descriptor */
    build_append_byte(var->buf, 9);    /* Length, bits[7:0] value = 9 */
    build_append_byte(var->buf, 0);    /* Length, bits[15:8] value = 0 */
    build_append_byte(var->buf, read_and_write); /* Write status, 1 rw 0 ro */

    /* Range base address */
    build_append_byte(var->buf, extract32(addr, 0, 8));  /* bits[7:0] */
    build_append_byte(var->buf, extract32(addr, 8, 8));  /* bits[15:8] */
    build_append_byte(var->buf, extract32(addr, 16, 8)); /* bits[23:16] */
    build_append_byte(var->buf, extract32(addr, 24, 8)); /* bits[31:24] */

    /* Range length */
    build_append_byte(var->buf, extract32(size, 0, 8));  /* bits[7:0] */
    build_append_byte(var->buf, extract32(size, 8, 8));  /* bits[15:8] */
    build_append_byte(var->buf, extract32(size, 16, 8)); /* bits[23:16] */
    build_append_byte(var->buf, extract32(size, 24, 8)); /* bits[31:24] */
    return var;
}
Beispiel #25
0
/*
 * Dino can forward memory accesses from the CPU in the range between
 * 0xf0800000 and 0xff000000 to the PCI bus.
 */
static void gsc_to_pci_forwarding(DinoState *s)
{
    uint32_t io_addr_en, tmp;
    int enabled, i;

    tmp = extract32(s->io_control, 7, 2);
    enabled = (tmp == 0x01);
    io_addr_en = s->io_addr_en;

    memory_region_transaction_begin();
    for (i = 1; i < 31; i++) {
        MemoryRegion *mem = &s->pci_mem_alias[i];
        if (enabled && (io_addr_en & (1U << i))) {
            if (!memory_region_is_mapped(mem)) {
                uint32_t addr = 0xf0000000 + i * DINO_MEM_CHUNK_SIZE;
                memory_region_add_subregion(get_system_memory(), addr, mem);
            }
        } else if (memory_region_is_mapped(mem)) {
            memory_region_del_subregion(get_system_memory(), mem);
        }
    }
    memory_region_transaction_commit();
}
Beispiel #26
0
static void imx_i2c_write(void *opaque, hwaddr offset,
                          uint64_t value, unsigned size)
{
    IMXI2CState *s = IMX_I2C(opaque);

    DPRINTF("write %s [0x%" HWADDR_PRIx "] <- 0x%02x\n",
            imx_i2c_get_regname(offset), offset, (int)value);

    value &= 0xff;

    switch (offset) {
    case IADR_ADDR:
        s->iadr = value & IADR_MASK;
        /* i2c_set_slave_address(s->bus, (uint8_t)s->iadr); */
        break;
    case IFDR_ADDR:
        s->ifdr = value & IFDR_MASK;
        break;
    case I2CR_ADDR:
        if (imx_i2c_is_enabled(s) && ((value & I2CR_IEN) == 0)) {
            /* This is a soft reset. IADR is preserved during soft resets */
            uint16_t iadr = s->iadr;
            imx_i2c_reset(DEVICE(s));
            s->iadr = iadr;
        } else { /* normal write */
            s->i2cr = value & I2CR_MASK;

            if (imx_i2c_is_master(s)) {
                /* set the bus to busy */
                s->i2sr |= I2SR_IBB;
            } else { /* slave mode */
                /* bus is not busy anymore */
                s->i2sr &= ~I2SR_IBB;

                /*
                 * if we unset the master mode then it ends the ongoing
                 * transfer if any
                 */
                if (s->address != ADDR_RESET) {
                    i2c_end_transfer(s->bus);
                    s->address = ADDR_RESET;
                }
            }

            if (s->i2cr & I2CR_RSTA) { /* Restart */
                /* if this is a restart then it ends the ongoing transfer */
                if (s->address != ADDR_RESET) {
                    i2c_end_transfer(s->bus);
                    s->address = ADDR_RESET;
                    s->i2cr &= ~I2CR_RSTA;
                }
            }
        }
        break;
    case I2SR_ADDR:
        /*
         * if the user writes 0 to IIF then lower the interrupt and
         * reset the bit
         */
        if ((s->i2sr & I2SR_IIF) && !(value & I2SR_IIF)) {
            s->i2sr &= ~I2SR_IIF;
            qemu_irq_lower(s->irq);
        }

        /*
         * if the user writes 0 to IAL, reset the bit
         */
        if ((s->i2sr & I2SR_IAL) && !(value & I2SR_IAL)) {
            s->i2sr &= ~I2SR_IAL;
        }

        break;
    case I2DR_ADDR:
        /* if the device is not enabled, nothing to do */
        if (!imx_i2c_is_enabled(s)) {
            break;
        }

        s->i2dr_write = value & I2DR_MASK;

        if (imx_i2c_is_master(s)) {
            /* If this is the first write cycle then it is the slave addr */
            if (s->address == ADDR_RESET) {
                if (i2c_start_transfer(s->bus, extract32(s->i2dr_write, 1, 7),
                                       extract32(s->i2dr_write, 0, 1))) {
                    /* if non zero is returned, the adress is not valid */
                    s->i2sr |= I2SR_RXAK;
                } else {
                    s->address = s->i2dr_write;
                    s->i2sr &= ~I2SR_RXAK;
                    imx_i2c_raise_interrupt(s);
                }
            } else { /* This is a normal data write */
                if (i2c_send(s->bus, s->i2dr_write)) {
                    /* if the target return non zero then end the transfer */
                    s->i2sr |= I2SR_RXAK;
                    s->address = ADDR_RESET;
                    i2c_end_transfer(s->bus);
                } else {
                    s->i2sr &= ~I2SR_RXAK;
                    imx_i2c_raise_interrupt(s);
                }
            }
        } else {
            qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n",
                          TYPE_IMX_I2C, __func__);
        }
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
                      HWADDR_PRIx "\n", TYPE_IMX_I2C, __func__, offset);
        break;
    }
}
Beispiel #27
0
static void complete_collecting_data(Flash *s)
{
    int i, n;

    n = get_addr_length(s);
    s->cur_addr = (n == 3 ? s->ear : 0);
    for (i = 0; i < n; ++i) {
        s->cur_addr <<= 8;
        s->cur_addr |= s->data[i];
    }

    s->cur_addr &= s->size - 1;

    s->state = STATE_IDLE;

    switch (s->cmd_in_progress) {
    case DPP:
    case QPP:
    case QPP_4:
    case PP:
    case PP4:
    case PP4_4:
        s->state = STATE_PAGE_PROGRAM;
        break;
    case READ:
    case READ4:
    case FAST_READ:
    case FAST_READ4:
    case DOR:
    case DOR4:
    case QOR:
    case QOR4:
    case DIOR:
    case DIOR4:
    case QIOR:
    case QIOR4:
        s->state = STATE_READ;
        break;
    case ERASE_4K:
    case ERASE4_4K:
    case ERASE_32K:
    case ERASE4_32K:
    case ERASE_SECTOR:
    case ERASE4_SECTOR:
    case DIE_ERASE:
        flash_erase(s, s->cur_addr, s->cmd_in_progress);
        break;
    case WRSR:
        switch (get_man(s)) {
        case MAN_SPANSION:
            s->quad_enable = !!(s->data[1] & 0x02);
            break;
        case MAN_MACRONIX:
            s->quad_enable = extract32(s->data[0], 6, 1);
            if (s->len > 1) {
                s->four_bytes_address_mode = extract32(s->data[1], 5, 1);
            }
            break;
        default:
            break;
        }
        if (s->write_enable) {
            s->write_enable = false;
        }
        break;
    case BRWR:
    case EXTEND_ADDR_WRITE:
        s->ear = s->data[0];
        break;
    case WNVCR:
        s->nonvolatile_cfg = s->data[0] | (s->data[1] << 8);
        break;
    case WVCR:
        s->volatile_cfg = s->data[0];
        break;
    case WEVCR:
        s->enh_volatile_cfg = s->data[0];
        break;
    case RDID_90:
    case RDID_AB:
        if (get_man(s) == MAN_SST) {
            if (s->cur_addr <= 1) {
                if (s->cur_addr) {
                    s->data[0] = s->pi->id[2];
                    s->data[1] = s->pi->id[0];
                } else {
                    s->data[0] = s->pi->id[0];
                    s->data[1] = s->pi->id[2];
                }
                s->pos = 0;
                s->len = 2;
                s->data_read_loop = true;
                s->state = STATE_READING_DATA;
            } else {
                qemu_log_mask(LOG_GUEST_ERROR,
                              "M25P80: Invalid read id address\n");
            }
        } else {
            qemu_log_mask(LOG_GUEST_ERROR,
                          "M25P80: Read id (command 0x90/0xAB) is not supported"
                          " by device\n");
        }
        break;
    default:
        break;
    }
}
Beispiel #28
0
static void reset_memory(Flash *s)
{
    s->cmd_in_progress = NOP;
    s->cur_addr = 0;
    s->ear = 0;
    s->four_bytes_address_mode = false;
    s->len = 0;
    s->needed_bytes = 0;
    s->pos = 0;
    s->state = STATE_IDLE;
    s->write_enable = false;
    s->reset_enable = false;
    s->quad_enable = false;

    switch (get_man(s)) {
    case MAN_NUMONYX:
        s->volatile_cfg = 0;
        s->volatile_cfg |= VCFG_DUMMY;
        s->volatile_cfg |= VCFG_WRAP_SEQUENTIAL;
        if ((s->nonvolatile_cfg & NVCFG_XIP_MODE_MASK)
                                != NVCFG_XIP_MODE_DISABLED) {
            s->volatile_cfg |= VCFG_XIP_MODE_ENABLED;
        }
        s->volatile_cfg |= deposit32(s->volatile_cfg,
                            VCFG_DUMMY_CLK_POS,
                            CFG_DUMMY_CLK_LEN,
                            extract32(s->nonvolatile_cfg,
                                        NVCFG_DUMMY_CLK_POS,
                                        CFG_DUMMY_CLK_LEN)
                            );

        s->enh_volatile_cfg = 0;
        s->enh_volatile_cfg |= EVCFG_OUT_DRIVER_STRENGHT_DEF;
        s->enh_volatile_cfg |= EVCFG_VPP_ACCELERATOR;
        s->enh_volatile_cfg |= EVCFG_RESET_HOLD_ENABLED;
        if (s->nonvolatile_cfg & NVCFG_DUAL_IO_MASK) {
            s->enh_volatile_cfg |= EVCFG_DUAL_IO_ENABLED;
        }
        if (s->nonvolatile_cfg & NVCFG_QUAD_IO_MASK) {
            s->enh_volatile_cfg |= EVCFG_QUAD_IO_ENABLED;
        }
        if (!(s->nonvolatile_cfg & NVCFG_4BYTE_ADDR_MASK)) {
            s->four_bytes_address_mode = true;
        }
        if (!(s->nonvolatile_cfg & NVCFG_LOWER_SEGMENT_MASK)) {
            s->ear = s->size / MAX_3BYTES_SIZE - 1;
        }
        break;
    case MAN_MACRONIX:
        s->volatile_cfg = 0x7;
        break;
    case MAN_SPANSION:
        s->spansion_cr1v = s->spansion_cr1nv;
        s->spansion_cr2v = s->spansion_cr2nv;
        s->spansion_cr3v = s->spansion_cr3nv;
        s->spansion_cr4v = s->spansion_cr4nv;
        s->quad_enable = extract32(s->spansion_cr1v,
                                   SPANSION_QUAD_CFG_POS,
                                   SPANSION_QUAD_CFG_LEN
                                   );
        s->four_bytes_address_mode = extract32(s->spansion_cr2v,
                SPANSION_ADDR_LEN_POS,
                SPANSION_ADDR_LEN_LEN
                );
        break;
    default:
        break;
    }

    DB_PRINT_L(0, "Reset done.\n");
}
Beispiel #29
0
static void complete_collecting_data(Flash *s)
{
    int i, n;

    n = get_addr_length(s);
    s->cur_addr = (n == 3 ? s->ear : 0);
    for (i = 0; i < n; ++i) {
        s->cur_addr <<= 8;
        s->cur_addr |= s->data[i];
    }

    s->cur_addr &= s->size - 1;

    s->state = STATE_IDLE;

    switch (s->cmd_in_progress) {
    case DPP:
    case QPP:
    case PP:
    case PP4:
    case PP4_4:
        s->state = STATE_PAGE_PROGRAM;
        break;
    case READ:
    case READ4:
    case FAST_READ:
    case FAST_READ4:
    case DOR:
    case DOR4:
    case QOR:
    case QOR4:
    case DIOR:
    case DIOR4:
    case QIOR:
    case QIOR4:
        s->state = STATE_READ;
        break;
    case ERASE_4K:
    case ERASE4_4K:
    case ERASE_32K:
    case ERASE4_32K:
    case ERASE_SECTOR:
    case ERASE4_SECTOR:
        flash_erase(s, s->cur_addr, s->cmd_in_progress);
        break;
    case WRSR:
        switch (get_man(s)) {
        case MAN_SPANSION:
            s->quad_enable = !!(s->data[1] & 0x02);
            break;
        case MAN_MACRONIX:
            s->quad_enable = extract32(s->data[0], 6, 1);
            if (s->len > 1) {
                s->four_bytes_address_mode = extract32(s->data[1], 5, 1);
            }
            break;
        default:
            break;
        }
        if (s->write_enable) {
            s->write_enable = false;
        }
        break;
    case EXTEND_ADDR_WRITE:
        s->ear = s->data[0];
        break;
    case WNVCR:
        s->nonvolatile_cfg = s->data[0] | (s->data[1] << 8);
        break;
    case WVCR:
        s->volatile_cfg = s->data[0];
        break;
    case WEVCR:
        s->enh_volatile_cfg = s->data[0];
        break;
    default:
        break;
    }
}
Beispiel #30
0
static void arm_sysctl_write(void *opaque, hwaddr offset,
                             uint64_t val, unsigned size)
{
    arm_sysctl_state *s = (arm_sysctl_state *)opaque;

    switch (offset) {
    case 0x08: /* LED */
        s->leds = val;
        break;
    case 0x0c: /* OSC0 */
    case 0x10: /* OSC1 */
    case 0x14: /* OSC2 */
    case 0x18: /* OSC3 */
    case 0x1c: /* OSC4 */
        /* ??? */
        break;
    case 0x20: /* LOCK */
        if (val == LOCK_VALUE)
            s->lockval = val;
        else
            s->lockval = val & 0x7fff;
        break;
    case 0x28: /* CFGDATA1 */
        /* ??? Need to implement this.  */
        s->cfgdata1 = val;
        break;
    case 0x2c: /* CFGDATA2 */
        /* ??? Need to implement this.  */
        s->cfgdata2 = val;
        break;
    case 0x30: /* FLAGSSET */
        s->flags |= val;
        break;
    case 0x34: /* FLAGSCLR */
        s->flags &= ~val;
        break;
    case 0x38: /* NVFLAGSSET */
        s->nvflags |= val;
        break;
    case 0x3c: /* NVFLAGSCLR */
        s->nvflags &= ~val;
        break;
    case 0x40: /* RESETCTL */
        switch (board_id(s)) {
        case BOARD_ID_PB926:
            if (s->lockval == LOCK_VALUE) {
                s->resetlevel = val;
                if (val & 0x100) {
                    qemu_system_reset_request();
                }
            }
            break;
        case BOARD_ID_PBX:
        case BOARD_ID_PBA8:
            if (s->lockval == LOCK_VALUE) {
                s->resetlevel = val;
                if (val & 0x04) {
                    qemu_system_reset_request();
                }
            }
            break;
        case BOARD_ID_VEXPRESS:
        case BOARD_ID_EB:
        default:
            /* reserved: RAZ/WI */
            break;
        }
        break;
    case 0x44: /* PCICTL */
        /* nothing to do.  */
        break;
    case 0x4c: /* FLASH */
        break;
    case 0x50: /* CLCD */
        switch (board_id(s)) {
        case BOARD_ID_PB926:
            /* On 926 bits 13:8 are R/O, bits 1:0 control
             * the mux that defines how to interpret the PL110
             * graphics format, and other bits are r/w but we
             * don't implement them to do anything.
             */
            s->sys_clcd &= 0x3f00;
            s->sys_clcd |= val & ~0x3f00;
            qemu_set_irq(s->pl110_mux_ctrl, val & 3);
            break;
        case BOARD_ID_EB:
            /* The EB is the same except that there is no mux since
             * the EB has a PL111.
             */
            s->sys_clcd &= 0x3f00;
            s->sys_clcd |= val & ~0x3f00;
            break;
        case BOARD_ID_PBA8:
        case BOARD_ID_PBX:
            /* On PBA8 and PBX bit 7 is r/w and all other bits
             * are either r/o or RAZ/WI.
             */
            s->sys_clcd &= (1 << 7);
            s->sys_clcd |= val & ~(1 << 7);
            break;
        case BOARD_ID_VEXPRESS:
        default:
            /* On VExpress this register is unimplemented and will RAZ/WI */
            break;
        }
        break;
    case 0x54: /* CLCDSER */
    case 0x64: /* DMAPSR0 */
    case 0x68: /* DMAPSR1 */
    case 0x6c: /* DMAPSR2 */
    case 0x70: /* IOSEL */
    case 0x74: /* PLDCTL */
    case 0x80: /* BUSID */
    case 0x84: /* PROCID0 */
    case 0x88: /* PROCID1 */
    case 0x8c: /* OSCRESET0 */
    case 0x90: /* OSCRESET1 */
    case 0x94: /* OSCRESET2 */
    case 0x98: /* OSCRESET3 */
    case 0x9c: /* OSCRESET4 */
        break;
    case 0xa0: /* SYS_CFGDATA */
        if (board_id(s) != BOARD_ID_VEXPRESS) {
            goto bad_reg;
        }
        s->sys_cfgdata = val;
        return;
    case 0xa4: /* SYS_CFGCTRL */
        if (board_id(s) != BOARD_ID_VEXPRESS) {
            goto bad_reg;
        }
        /* Undefined bits [19:18] are RAZ/WI, and writing to
         * the start bit just triggers the action; it always reads
         * as zero.
         */
        s->sys_cfgctrl = val & ~((3 << 18) | (1 << 31));
        if (val & (1 << 31)) {
            /* Start bit set -- actually do something */
            unsigned int dcc = extract32(s->sys_cfgctrl, 26, 4);
            unsigned int function = extract32(s->sys_cfgctrl, 20, 6);
            unsigned int site = extract32(s->sys_cfgctrl, 16, 2);
            unsigned int position = extract32(s->sys_cfgctrl, 12, 4);
            unsigned int device = extract32(s->sys_cfgctrl, 0, 12);
            s->sys_cfgstat = 1;            /* complete */
            if (s->sys_cfgctrl & (1 << 30)) {
                if (!vexpress_cfgctrl_write(s, dcc, function, site, position,
                                            device, s->sys_cfgdata)) {
                    s->sys_cfgstat |= 2;        /* error */
                }
            } else {
                uint32_t val;
                if (!vexpress_cfgctrl_read(s, dcc, function, site, position,
                                           device, &val)) {
                    s->sys_cfgstat |= 2;        /* error */
                } else {
                    s->sys_cfgdata = val;
                }
            }
        }
        s->sys_cfgctrl &= ~(1 << 31);
        return;
    case 0xa8: /* SYS_CFGSTAT */
        if (board_id(s) != BOARD_ID_VEXPRESS) {
            goto bad_reg;
        }
        s->sys_cfgstat = val & 3;
        return;
    default:
    bad_reg:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "arm_sysctl_write: Bad register offset 0x%x\n",
                      (int)offset);
        return;
    }
}