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); }
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); } } }
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; }
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; } } }
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)); }
/* * 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); } }
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); }
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)); } } }
static void a10_pit_set_freq(AwA10PITState *s, int index) { uint32_t prescaler, source, source_freq; prescaler = 1 << extract32(s->control[index], 4, 3); source = extract32(s->control[index], 2, 2); source_freq = s->clk_freq[source]; if (source_freq) { ptimer_set_freq(s->timer[index], source_freq / prescaler); } else { qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid clock source %u\n", __func__, source); } }
static void digic_timer_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); } }
inline void extract(const std::vector<unsigned char> &vec, size_t &offset, unsigned &target) { target = extract32(vec, offset); offset += 4; }
/* 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, ®, false); for (j = 0; j < regsz; j++) { field = extract32(reg, j * width, width); translate_fn(s, irq + j, cpu, &field, false); } cpu++; } offset += 4; }
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)); }
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); }
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); }
static void imx_epit_set_freq(IMXEPITState *s) { uint32_t clksrc; uint32_t prescaler; uint32_t freq; clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2); prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12); freq = imx_clock_frequency(s->ccm, imx_epit_clocks[clksrc]) / prescaler; s->freq = freq; DPRINTF("Setting ptimer frequency to %u\n", freq); if (freq) { ptimer_set_freq(s->timer_reload, freq); ptimer_set_freq(s->timer_cmp, freq); } }
static 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; }
static void imx_gpt_set_freq(IMXGPTState *s) { uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3); uint32_t freq = imx_clock_frequency(s->ccm, imx_gpt_clocks[clksrc]) / (1 + s->pr); s->freq = freq; DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, freq); if (freq) { ptimer_set_freq(s->timer, freq); } }
static void 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])); }
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; }
/* 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); }
/* * 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; }
/* * 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(); }
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; } }
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; } }
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"); }
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; } }
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; } }