static int pca954x_event(I2CSlave *i2c, enum i2c_event event) { PCA954XState *s = PCA954X(i2c); int i; s->event = event; for (i = 0; i < s->lanes; ++i) { if (s->active_lanes & (1 << i)) { switch (event) { /* defer START conditions until we have an address */ case I2C_START_SEND: case I2C_START_RECV: break; /* Forward others to sub busses */ case I2C_FINISH: if (!s->control_decoded) { DB_PRINT("stopping active bus %d\n", i); i2c_end_transfer(s->busses[i]); } break; case I2C_NACK: if (!s->control_decoded) { DB_PRINT("nacking active bus %d\n", i); i2c_nack(s->busses[i]); } break; } } } return 0; }
/* * init the epg db * buffer: IN, db node table. */ INT32 init_epg_db(OSAL_ID flag, UINT8 *buffer, UINT32 buf_len) { if (buffer == NULL || buf_len == 0) { DB_PRINT("%s: buffer is NULL!\n",__FUNCTION__); return ERR_FAILED; } MEMSET(buffer, 0, buf_len); db_block.node = (struct DB_NODE*)buffer; db_block.max_count = buf_len / sizeof(struct DB_NODE); db_block.index = 0; db_block.count = 0; DB_PRINT("epg db buffer: 0x%X, len: %d, sizeof DB_NODE: %d, max count: %d\n", buffer, buf_len, sizeof(struct DB_NODE), db_block.max_count); if (flag == OSAL_INVALID_ID) { DB_PRINT("%s: flag ivalid!\n",__FUNCTION__); return ERR_FAILED; } db_block.flag = flag; #ifdef EPG_MULTI_TP g_update_all_events = FALSE; MEMSET(&epg_update_view, 0, sizeof(epg_update_view)); reset_multi_tp(); #endif osal_flag_set(db_block.flag, EPGDB_FLAG_MUTEX); return SUCCESS; }
static void spi_flush_txfifo(XilinxSPI *s) { uint32_t tx; uint32_t rx; while (!fifo8_is_empty(&s->tx_fifo)) { tx = (uint32_t)fifo8_pop(&s->tx_fifo); DB_PRINT("data tx:%x\n", tx); rx = ssi_transfer(s->spi, tx); DB_PRINT("data rx:%x\n", rx); if (fifo8_is_full(&s->rx_fifo)) { s->regs[R_IPISR] |= IRQ_DRR_OVERRUN; } else { fifo8_push(&s->rx_fifo, (uint8_t)rx); if (fifo8_is_full(&s->rx_fifo)) { s->regs[R_SPISR] |= SR_RX_FULL; s->regs[R_IPISR] |= IRQ_DRR_FULL; } } s->regs[R_SPISR] &= ~SR_RX_EMPTY; s->regs[R_SPISR] &= ~SR_TX_FULL; s->regs[R_SPISR] |= SR_TX_EMPTY; s->regs[R_IPISR] |= IRQ_DTR_EMPTY; s->regs[R_IPISR] |= IRQ_DRR_NOT_EMPTY; } }
static void xilinx_spips_flush_txfifo(XilinxSPIPS *s) { for (;;) { int i; uint8_t rx; uint8_t tx = 0; for (i = 0; i < num_effective_busses(s); ++i) { if (!i || s->snoop_state == SNOOP_STRIPING) { if (fifo8_is_empty(&s->tx_fifo)) { s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW; xilinx_spips_update_ixr(s); return; } else { tx = fifo8_pop(&s->tx_fifo); } } rx = ssi_transfer(s->spi[i], (uint32_t)tx); DB_PRINT("tx = %02x rx = %02x\n", tx, rx); if (!i || s->snoop_state == SNOOP_STRIPING) { if (fifo8_is_full(&s->rx_fifo)) { s->regs[R_INTR_STATUS] |= IXR_RX_FIFO_OVERFLOW; DB_PRINT("rx FIFO overflow"); } else { fifo8_push(&s->rx_fifo, (uint8_t)rx); } } } switch (s->snoop_state) { case (SNOOP_CHECKING): switch (tx) { /* new instruction code */ case READ: /* 3 address bytes, no dummy bytes/cycles */ case PP: case DPP: case QPP: s->snoop_state = 3; break; case FAST_READ: /* 3 address bytes, 1 dummy byte */ case DOR: case QOR: case DIOR: /* FIXME: these vary between vendor - set to spansion */ s->snoop_state = 4; break; case QIOR: /* 3 address bytes, 2 dummy bytes */ s->snoop_state = 6; break; default: s->snoop_state = SNOOP_NONE; } break; case (SNOOP_STRIPING): case (SNOOP_NONE): break; default: s->snoop_state--; } } }
void fdt_init_yield(FDTMachineInfo *fdti) { static int yield_index; int this_yield = yield_index++; DB_PRINT(1, "Yield #%d\n", this_yield); qemu_co_queue_wait(fdti->cq, NULL); DB_PRINT(1, "Unyield #%d\n", this_yield); }
static int xilinx_spi_init(SysBusDevice *sbd) { DeviceState *dev = DEVICE(sbd); XilinxSPI *s = XILINX_SPI(dev); int i; DB_PRINT("\n"); s->spi = ssi_create_bus(dev, "spi"); sysbus_init_irq(sbd, &s->irq); s->cs_lines = g_new0(qemu_irq, s->num_cs); ssi_auto_connect_slaves(dev, s->cs_lines, s->spi); for (i = 0; i < s->num_cs; ++i) { sysbus_init_irq(sbd, &s->cs_lines[i]); } memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s, "xilinx-spi", R_MAX * 4); sysbus_init_mmio(sbd, &s->mmio); s->irqline = -1; fifo8_create(&s->tx_fifo, FIFO_CAPACITY); fifo8_create(&s->rx_fifo, FIFO_CAPACITY); return 0; }
static void xilinx_spips_update_cs_lines(XilinxSPIPS *s) { int i, j; bool found = false; int field = s->regs[R_CONFIG] >> CS_SHIFT; for (i = 0; i < s->num_cs; i++) { for (j = 0; j < num_effective_busses(s); j++) { int upage = !!(s->regs[R_LQSPI_STS] & LQSPI_CFG_U_PAGE); int cs_to_set = (j * s->num_cs + i + upage) % (s->num_cs * s->num_busses); if (~field & (1 << i) && !found) { DB_PRINT("selecting slave %d\n", i); qemu_set_irq(s->cs_lines[cs_to_set], 0); } else { qemu_set_irq(s->cs_lines[cs_to_set], 1); } } if (~field & (1 << i)) { found = true; } } if (!found) { s->snoop_state = SNOOP_CHECKING; } }
static uint64_t stm32f2xx_syscfg_read(void *opaque, hwaddr addr, unsigned int size) { STM32F2XXSyscfgState *s = opaque; DB_PRINT("0x%"HWADDR_PRIx"\n", addr); switch (addr) { case SYSCFG_MEMRMP: return s->syscfg_memrmp; case SYSCFG_PMC: return s->syscfg_pmc; case SYSCFG_EXTICR1: return s->syscfg_exticr1; case SYSCFG_EXTICR2: return s->syscfg_exticr2; case SYSCFG_EXTICR3: return s->syscfg_exticr3; case SYSCFG_EXTICR4: return s->syscfg_exticr4; case SYSCFG_CMPCR: return s->syscfg_cmpcr; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); return 0; } return 0; }
static int pca954x_decode_address(I2CSlave *i2c, uint8_t address) { PCA954XState *s = PCA954X(i2c); int i; uint8_t channel_status = 0; s->control_decoded = address == (PCA954X_CONTROL_ADDR | (s->chip_enable & 0x7)); if (s->control_decoded) { return 0; } for (i = 0; i < s->lanes; ++i) { if (s->active_lanes & (1 << i)) { DB_PRINT("starting active bus %d addr:%02x rnw:%d\n", i, address, s->event == I2C_START_RECV); channel_status |= (i2c_start_transfer(s->busses[i], address, s->event == I2C_START_RECV)) << i; } } if (s->active_lanes == channel_status) { return 1; } return 0; }
int simple_bus_fdt_init(char *bus_node_path, FDTMachineInfo *fdti, void *unused) { int i; int num_children = qemu_devtree_get_num_children(fdti->fdt, bus_node_path, 1); char **children = qemu_devtree_get_children(fdti->fdt, bus_node_path, 1); int initialRoutinesPending = fdti->routinesPending; DB_PRINT("num child devices: %d\n", num_children); for (i = 0; i < num_children; i++) { struct FDTInitNodeArgs *init_args = g_malloc0(sizeof(*init_args)); init_args->node_path = children[i]; init_args->fdti = fdti; fdti->routinesPending++; qemu_coroutine_enter(qemu_coroutine_create(fdt_init_node), init_args); } if (fdti->routinesPending != initialRoutinesPending) { bdrv_drain_all(); } g_free(children); return 0; }
static int xilinx_spi_init(SysBusDevice *dev) { int i; XilinxSPI *s = FROM_SYSBUS(typeof(*s), dev); DB_PRINT("\n"); s->spi = ssi_create_bus(&dev->qdev, "spi"); sysbus_init_irq(dev, &s->irq); s->cs_lines = g_new(qemu_irq, s->num_cs); ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi); for (i = 0; i < s->num_cs; ++i) { sysbus_init_irq(dev, &s->cs_lines[i]); } memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s, "xilinx-spi", R_MAX * 4); sysbus_init_mmio(dev, &s->mmio); s->irqline = -1; fifo8_create(&s->tx_fifo, FIFO_CAPACITY); fifo8_create(&s->rx_fifo, FIFO_CAPACITY); return 0; }
FDTMachineInfo *fdt_generic_create_machine(void *fdt, qemu_irq *cpu_irq) { char node_path[DT_PATH_LENGTH]; FDTMachineInfo *fdti = fdt_init_new_fdti(fdt); fdti->irq_base = cpu_irq; /* parse the device tree */ if (!qemu_devtree_get_root_node(fdt, node_path)) { memory_region_transaction_begin(); fdt_init_set_opaque(fdti, node_path, NULL); simple_bus_fdt_init(node_path, fdti); while (qemu_co_enter_next(fdti->cq)); fdt_init_all_irqs(fdti); memory_region_transaction_commit(); } else { fprintf(stderr, "FDT: ERROR: cannot get root node from device tree %s\n" , node_path); } DB_PRINT(0, "FDT: Device tree scan complete\n"); FDTMachineInfo *ret = g_malloc0(sizeof(*ret)); return fdti; }
static void xlnx_zynqmp_ipi_update_irq(XlnxZynqMPIPI *s) { bool pending = s->regs[R_IPI_ISR] & ~s->regs[R_IPI_IMR]; DB_PRINT("irq=%d isr=%x mask=%x\n", pending, s->regs[R_IPI_ISR], s->regs[R_IPI_IMR]); qemu_set_irq(s->irq, pending); }
static void ipi_update_irq(IPI *s) { bool pending = s->regs[R_IPI_ISR] & ~s->regs[R_IPI_IMR]; DB_PRINT("%s: irq=%d isr=%x mask=%x\n", object_get_canonical_path(OBJECT(s)), pending, s->regs[R_IPI_ISR], s->regs[R_IPI_IMR]); qemu_set_irq(s->irq, pending); }
static uint64_t zynq_slcr_read(void *opaque, hwaddr offset, unsigned size) { uint32_t ret = zynq_slcr_read_imp(opaque, offset); DB_PRINT("addr: %08x data: %08x\n", offset, ret); return ret; }
static void xlnx_zynqmp_obs_handler(void *opaque, int n, int level) { XlnxZynqMPIPI *s = XLNX_ZYNQMP_IPI(opaque); DB_PRINT("OBS input irq[%d]=%d\n", n, level); s->regs[R_IPI_OBS] &= ~(1ULL << n); s->regs[R_IPI_OBS] |= (level << n); }
static void xlnx_zynqmp_ipi_handler(void *opaque, int n, int level) { XlnxZynqMPIPI *s = XLNX_ZYNQMP_IPI(opaque); uint32_t val = (!!level) << n; DB_PRINT("IPI input irq[%d]=%d\n", n, level); s->regs[R_IPI_ISR] |= val; xlnx_zynqmp_ipi_set_obs(s, s->regs[R_IPI_ISR]); xlnx_zynqmp_ipi_update_irq(s); }
static int pca954x_recv(I2CSlave *i2c) { PCA954XState *s = PCA954X(i2c); int i; int ret = 0; if (s->control_decoded) { ret |= s->control_reg; DB_PRINT("returning control register: %x\n", ret); } else { for (i = 0; i < s->lanes; ++i) { if (s->active_lanes & (1 << i)) { ret |= i2c_recv(s->busses[i]); DB_PRINT("recieving from active bus %d:%x\n", i, ret); } } } return ret; }
static uint64_t stm32f2xx_timer_read(void *opaque, hwaddr offset, unsigned size) { STM32F2XXTimerState *s = opaque; DB_PRINT("Read 0x%"HWADDR_PRIx"\n", offset); switch (offset) { case TIM_CR1: return s->tim_cr1; case TIM_CR2: return s->tim_cr2; case TIM_SMCR: return s->tim_smcr; case TIM_DIER: return s->tim_dier; case TIM_SR: return s->tim_sr; case TIM_EGR: return s->tim_egr; case TIM_CCMR1: return s->tim_ccmr1; case TIM_CCMR2: return s->tim_ccmr2; case TIM_CCER: return s->tim_ccer; case TIM_CNT: return stm32f2xx_ns_to_ticks(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) - s->tick_offset; case TIM_PSC: return s->tim_psc; case TIM_ARR: return s->tim_arr; case TIM_CCR1: return s->tim_ccr1; case TIM_CCR2: return s->tim_ccr2; case TIM_CCR3: return s->tim_ccr3; case TIM_CCR4: return s->tim_ccr4; case TIM_DCR: return s->tim_dcr; case TIM_DMAR: return s->tim_dmar; case TIM_OR: return s->tim_or; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, offset); } return 0; }
static void stm32f2xx_timer_interrupt(void *opaque) { STM32F2XXTimerState *s = opaque; DB_PRINT("Interrupt\n"); if (s->tim_dier & TIM_DIER_UIE && s->tim_cr1 & TIM_CR1_CEN) { s->tim_sr |= 1; qemu_irq_pulse(s->irq); stm32f2xx_timer_set_alarm(s, s->hit_time); } }
static void xlnx_zynqmp_ipi_set_obs(XlnxZynqMPIPI *s, uint32_t val) { int i, ipi_index, ipi_mask; for (i = 0; i < NUM_IPIS; i++) { ipi_index = index_array[i]; ipi_mask = (1 << ipi_index); DB_PRINT("Setting %s=%d\n", index_array_names[i], !!(val & ipi_mask)); qemu_set_irq(s->irq_obs_out[i], !!(val & ipi_mask)); } }
static void stm32f2xx_timer_interrupt(void *opaque) { STM32F2XXTimerState *s = opaque; DB_PRINT("Interrupt\n"); if (s->tim_dier & TIM_DIER_UIE && s->tim_cr1 & TIM_CR1_CEN) { s->tim_sr |= 1; qemu_irq_pulse(s->irq); stm32f2xx_timer_set_alarm(s, s->hit_time); } if (s->tim_ccmr1 & (TIM_CCMR1_OC2M2 | TIM_CCMR1_OC2M1) && !(s->tim_ccmr1 & TIM_CCMR1_OC2M0) && s->tim_ccmr1 & TIM_CCMR1_OC2PE && s->tim_ccer & TIM_CCER_CC2E) { /* PWM 2 - Mode 1 */ DB_PRINT("PWM2 Duty Cycle: %d%%\n", s->tim_ccr2 / (100 * (s->tim_psc + 1))); } }
static inline void razwi_unimp_rw(void *opaque, hwaddr addr, uint64_t val64, unsigned int size, bool rnw) { char str[1024]; snprintf(str, sizeof(str), "%s: RAZ/WI device %s: addr: %#llx data: %#llx" " size: %d\n", opaque ? (const char *)opaque : "(none)", rnw ? "read" : "write", (unsigned long long)addr, (unsigned long long)val64, size); DB_PRINT(0, "%s", str); qemu_log_mask(LOG_UNIMP, "%s", str); }
static uint64_t xilinx_spips_read(void *opaque, hwaddr addr, unsigned size) { XilinxSPIPS *s = opaque; uint32_t mask = ~0; uint32_t ret; addr >>= 2; switch (addr) { case R_CONFIG: mask = 0x0002FFFF; break; case R_INTR_STATUS: case R_INTR_MASK: mask = IXR_ALL; break; case R_EN: mask = 0x1; break; case R_SLAVE_IDLE_COUNT: mask = 0xFF; break; case R_MOD_ID: mask = 0x01FFFFFF; break; case R_INTR_EN: case R_INTR_DIS: case R_TX_DATA: mask = 0; break; case R_RX_DATA: rx_data_bytes(s, &ret, s->num_txrx_bytes); DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret); xilinx_spips_update_ixr(s); return ret; } DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, s->regs[addr] & mask); return s->regs[addr] & mask; }
static void stm32f2xx_timer_set_alarm(STM32F2XXTimerState *s, int64_t now) { uint64_t ticks; int64_t now_ticks; if (s->tim_arr == 0) { return; } DB_PRINT("Alarm set at: 0x%x\n", s->tim_cr1); now_ticks = stm32f2xx_ns_to_ticks(s, now); ticks = s->tim_arr - (now_ticks - s->tick_offset); DB_PRINT("Alarm set in %d ticks\n", (int) ticks); s->hit_time = muldiv64((ticks + (uint64_t) now_ticks) * (s->tim_psc + 1), 1000000000ULL, s->freq_hz); timer_mod(s->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->hit_time); DB_PRINT("Wait Time: %" PRId64 " ticks\n", s->hit_time); }
static int pca954x_send(I2CSlave *i2c, uint8_t data) { PCA954XState *s = PCA954X(i2c); int i; int ret = -1; if (s->control_decoded) { DB_PRINT("setting control register: %x\n", data); s->control_reg = data; pca954x_decode_lane(s); ret = 0; } else { for (i = 0; i < s->lanes; ++i) { if (s->active_lanes & (1 << i)) { DB_PRINT("sending to active bus %d:%x\n", i, data); ret &= i2c_send(s->busses[i], data); } } } return ret; }
static void ipi_handler(void *opaque, int n, int level) { IPI *s = XILINX_IPI(opaque); DepRegisterInfo *r_isr = &s->regs_info[A_IPI_ISR / 4]; uint32_t val = (!!level) << n; uint64_t old_value = s->regs[R_IPI_ISR]; DB_PRINT("%s: %s: irq[%d]=%d\n", __func__, object_get_canonical_path(OBJECT(s)), n, level); s->regs[R_IPI_ISR] |= val; ipi_update_irq(s); dep_register_refresh_gpios(r_isr, old_value); }
static void fdt_init_all_irqs(FDTMachineInfo *fdti) { while (fdti->irqs) { FDTIRQConnection *first = fdti->irqs; qemu_irq sink = first->irq; bool (*merge_fn)(bool *, int) = first->merge_fn; int num_sources = 0; FDTIRQConnection *irq; for (irq = first; irq; irq = irq->next) { if (irq->irq == sink) { /* Same sink */ num_sources++; } } if (num_sources > 1) { QEMUIRQSharedState *s = g_malloc0(sizeof *s); s->sink = sink; s->merge_fn = merge_fn; qemu_irq *sources = qemu_allocate_irqs(qemu_irq_shared_handler, s, num_sources); for (irq = first; irq; irq = irq->next) { if (irq->irq == sink) { char *shared_irq_name = g_strdup_printf("shared-irq-%p", *sources); if (irq->merge_fn != merge_fn) { fprintf(stderr, "ERROR: inconsistent IRQ merge fns\n"); exit(1); } object_property_add_child(OBJECT(irq->dev), shared_irq_name, OBJECT(*sources), &error_abort); g_free(shared_irq_name); irq->irq = *(sources++); s->num++; } } } DB_PRINT(0, "%s: connected to %s irq line %d (%s)\n", first->sink_info ? first->sink_info : "", object_get_canonical_path(OBJECT(first->dev)), first->i, first->name ? first->name : ""); qdev_connect_gpio_out_named(DEVICE(first->dev), first->name, first->i, first->irq); fdti->irqs = first->next; g_free(first); } }
static uint64_t timer_read(void *opaque, hwaddr offset, unsigned int size) { MSSTimerState *t = opaque; hwaddr addr; struct Msf2Timer *st; uint32_t ret = 0; int timer = 0; int isr; int ier; addr = offset >> 2; /* * Two independent timers has same base address. * Based on address passed figure out which timer is being used. */ if ((addr >= R_TIM1_MAX) && (addr < NUM_TIMERS * R_TIM1_MAX)) { timer = 1; addr -= R_TIM1_MAX; } st = &t->timers[timer]; switch (addr) { case R_TIM_VAL: ret = ptimer_get_count(st->ptimer); break; case R_TIM_MIS: isr = !!(st->regs[R_TIM_RIS] & TIMER_RIS_ACK); ier = !!(st->regs[R_TIM_CTRL] & TIMER_CTRL_INTR); ret = ier & isr; break; default: if (addr < R_TIM1_MAX) { ret = st->regs[addr]; } else { qemu_log_mask(LOG_GUEST_ERROR, TYPE_MSS_TIMER": 64-bit mode not supported\n"); return ret; } break; } DB_PRINT("timer=%d 0x%" HWADDR_PRIx "=0x%" PRIx32, timer, offset, ret); return ret; }
static uint64_t spi_read(void *opaque, hwaddr addr, unsigned int size) { XilinxSPI *s = opaque; uint32_t r = 0; addr >>= 2; switch (addr) { case R_SPIDRR: if (fifo8_is_empty(&s->rx_fifo)) { DB_PRINT("Read from empty FIFO!\n"); return 0xdeadbeef; } s->regs[R_SPISR] &= ~SR_RX_FULL; r = fifo8_pop(&s->rx_fifo); if (fifo8_is_empty(&s->rx_fifo)) { s->regs[R_SPISR] |= SR_RX_EMPTY; } break; case R_SPISR: r = s->regs[addr]; break; default: if (addr < ARRAY_SIZE(s->regs)) { r = s->regs[addr]; } break; } DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, r); xlx_spi_update_irq(s); return r; }