Commit 669b4983 authored by Peter A. G. Crosthwaite's avatar Peter A. G. Crosthwaite Committed by Edgar E. Iglesias
Browse files

xilinx_axi*: Re-implemented interconnect



Re-implemented the interconnect between the Xilinx AXI ethernet and DMA
controllers. A QOM interface "stream" is created, for the two stream interfaces.

As per Edgars request, this is designed to be more generic than AXI-stream,
so in the future we may see more clients of this interface beyond AXI stream.

This is based primarily on Paolos original refactoring of the interconnect.

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarPeter A.G. Crosthwaite <peter.crosthwaite@petalogix.com>
Signed-off-by: default avatarEdgar E. Iglesias <edgar.iglesias@gmail.com>
parent 346fe0c4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ hw-obj-$(CONFIG_XILINX) += xilinx_timer.o
hw-obj-$(CONFIG_XILINX) += xilinx_uartlite.o
hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o
hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
hw-obj-$(CONFIG_XILINX_AXI) += stream.o

# PKUnity SoC devices
hw-obj-$(CONFIG_PUV3) += puv3_intc.o
+14 −10
Original line number Diff line number Diff line
@@ -39,7 +39,8 @@

#include "microblaze_boot.h"
#include "microblaze_pic_cpu.h"
#include "xilinx_axidma.h"

#include "stream.h"

#define LMB_BRAM_SIZE  (128 * 1024)
#define FLASH_SIZE     (32 * 1024 * 1024)
@@ -76,7 +77,7 @@ petalogix_ml605_init(ram_addr_t ram_size,
                          const char *initrd_filename, const char *cpu_model)
{
    MemoryRegion *address_space_mem = get_system_memory();
    DeviceState *dev;
    DeviceState *dev, *dma, *eth0;
    MicroBlazeCPU *cpu;
    CPUMBState *env;
    DriveInfo *dinfo;
@@ -125,15 +126,18 @@ petalogix_ml605_init(ram_addr_t ram_size,
    /* 2 timers at irq 2 @ 100 Mhz.  */
    xilinx_timer_create(TIMER_BASEADDR, irq[2], 0, 100 * 1000000);

    /* axi ethernet and dma initialization. TODO: Dynamically connect them.  */
    {
        static struct XilinxDMAConnection dmach;
    /* axi ethernet and dma initialization. */
    dma = qdev_create(NULL, "xlnx.axi-dma");

        xilinx_axiethernet_create(&dmach, &nd_table[0], 0x82780000,
                                  irq[3], 0x1000, 0x1000);
        xilinx_axiethernetdma_create(&dmach, 0x84600000,
                                     irq[1], irq[0], 100 * 1000000);
    }
    /* FIXME: attach to the sysbus instead */
    object_property_add_child(container_get(qdev_get_machine(), "/unattached"),
                                  "xilinx-dma", OBJECT(dma), NULL);

    eth0 = xilinx_axiethernet_create(&nd_table[0], STREAM_SLAVE(dma),
                                     0x82780000, irq[3], 0x1000, 0x1000);

    xilinx_axiethernetdma_init(dma, STREAM_SLAVE(eth0),
                               0x84600000, irq[1], irq[0], 100 * 1000000);

    microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
                                                            machine_cpu_reset);

hw/stream.c

0 → 100644
+23 −0
Original line number Diff line number Diff line
#include "stream.h"

void
stream_push(StreamSlave *sink, uint8_t *buf, size_t len, uint32_t *app)
{
    StreamSlaveClass *k =  STREAM_SLAVE_GET_CLASS(sink);

    k->push(sink, buf, len, app);
}

static TypeInfo stream_slave_info = {
    .name          = TYPE_STREAM_SLAVE,
    .parent        = TYPE_INTERFACE,
    .class_size = sizeof(StreamSlaveClass),
};


static void stream_slave_register_types(void)
{
    type_register_static(&stream_slave_info);
}

type_init(stream_slave_register_types)

hw/stream.h

0 → 100644
+31 −0
Original line number Diff line number Diff line
#ifndef STREAM_H
#define STREAM_H 1

#include "qemu-common.h"
#include "qemu/object.h"

/* stream slave. Used until qdev provides a generic way.  */
#define TYPE_STREAM_SLAVE "stream-slave"

#define STREAM_SLAVE_CLASS(klass) \
     OBJECT_CLASS_CHECK(StreamSlaveClass, (klass), TYPE_STREAM_SLAVE)
#define STREAM_SLAVE_GET_CLASS(obj) \
    OBJECT_GET_CLASS(StreamSlaveClass, (obj), TYPE_STREAM_SLAVE)
#define STREAM_SLAVE(obj) \
     INTERFACE_CHECK(StreamSlave, (obj), TYPE_STREAM_SLAVE)

typedef struct StreamSlave {
    Object Parent;
} StreamSlave;

typedef struct StreamSlaveClass {
    InterfaceClass parent;

    void (*push)(StreamSlave *obj, unsigned char *buf, size_t len,
                                                    uint32_t *app);
} StreamSlaveClass;

void
stream_push(StreamSlave *sink, uint8_t *buf, size_t len, uint32_t *app);

#endif /* STREAM_H */
+9 −13
Original line number Diff line number Diff line
#include "stream.h"
#include "qemu-common.h"
#include "net.h"

@@ -49,8 +50,8 @@ xilinx_ethlite_create(NICInfo *nd, target_phys_addr_t base, qemu_irq irq,
}

static inline DeviceState *
xilinx_axiethernet_create(void *dmach,
                          NICInfo *nd, target_phys_addr_t base, qemu_irq irq,
xilinx_axiethernet_create(NICInfo *nd, StreamSlave *peer,
                          target_phys_addr_t base, qemu_irq irq,
                          int txmem, int rxmem)
{
    DeviceState *dev;
@@ -60,7 +61,7 @@ xilinx_axiethernet_create(void *dmach,
    qdev_set_nic_properties(dev, nd);
    qdev_prop_set_uint32(dev, "rxmem", rxmem);
    qdev_prop_set_uint32(dev, "txmem", txmem);
    qdev_prop_set_ptr(dev, "dmach", dmach);
    object_property_set_link(OBJECT(dev), OBJECT(peer), "tx_dev", NULL);
    qdev_init_nofail(dev);
    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
@@ -68,21 +69,16 @@ xilinx_axiethernet_create(void *dmach,
    return dev;
}

static inline DeviceState *
xilinx_axiethernetdma_create(void *dmach,
static inline void
xilinx_axiethernetdma_init(DeviceState *dev, StreamSlave *peer,
                           target_phys_addr_t base, qemu_irq irq,
                           qemu_irq irq2, int freqhz)
{
    DeviceState *dev = NULL;

    dev = qdev_create(NULL, "xlnx.axi-dma");
    qdev_prop_set_uint32(dev, "freqhz", freqhz);
    qdev_prop_set_ptr(dev, "dmach", dmach);
    object_property_set_link(OBJECT(dev), OBJECT(peer), "tx_dev", NULL);
    qdev_init_nofail(dev);

    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
    sysbus_connect_irq(sysbus_from_qdev(dev), 1, irq2);

    return dev;
}
Loading