diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | hw/ssi.c | 52 | ||||
-rw-r--r-- | hw/ssi.h | 41 | ||||
-rw-r--r-- | qemu-common.h | 1 |
4 files changed, 95 insertions, 1 deletions
@@ -101,7 +101,7 @@ OBJS+=bt-hci-csr.o OBJS+=buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o OBJS+=qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o OBJS+=msmouse.o ps2.o -OBJS+=qdev.o +OBJS+=qdev.o ssi.o ifdef CONFIG_BRLAPI OBJS+= baum.o diff --git a/hw/ssi.c b/hw/ssi.c new file mode 100644 index 000000000..9dfdbe94f --- /dev/null +++ b/hw/ssi.c @@ -0,0 +1,52 @@ +/* + * QEMU Synchronous Serial Interface support + * + * Copyright (c) 2009 CodeSourcery. + * Written by Paul Brook + * + * This code is licenced under the GNU GPL v2. + */ + +#include "ssi.h" + +struct SSIBus { + SSISlave *slave; +}; + +static void ssi_slave_init(DeviceState *dev, void *opaque) +{ + SSISlaveInfo *info = opaque; + SSISlave *s = SSI_SLAVE_FROM_QDEV(dev); + SSIBus *bus = qdev_get_bus(dev); + + bus->slave = s; + s->info = info; + info->init(s); +} + +void ssi_register_slave(const char *name, int size, SSISlaveInfo *info) +{ + assert(size >= sizeof(SSISlave)); + qdev_register(name, size, ssi_slave_init, info); +} + +DeviceState *ssi_create_slave(SSIBus *bus, const char *name) +{ + DeviceState *dev; + dev = qdev_create(bus, name); + qdev_init(dev); + return dev; +} + +SSIBus *ssi_create_bus(void) +{ + return qemu_mallocz(sizeof(SSIBus)); +} + +uint32_t ssi_transfer(SSIBus *bus, uint32_t val) +{ + if (!bus->slave) { + return 0; + } + return bus->slave->info->transfer(bus->slave, val); +} diff --git a/hw/ssi.h b/hw/ssi.h new file mode 100644 index 000000000..d9865e64d --- /dev/null +++ b/hw/ssi.h @@ -0,0 +1,41 @@ +/* QEMU Synchronous Serial Interface support. */ + +/* In principle SSI is a point-point interface. As such the qemu + implementation has a single slave device on a "bus". + However it is fairly common for boards to have multiple slaves + connected to a single master, and select devices with an external + chip select. This is implemented in qemu by having an explicit mux device. + It is assumed that master and slave are both using the same transfer width. + */ + +#ifndef QEMU_SSI_H +#define QEMU_SSI_H + +#include "qdev.h" + +typedef struct SSISlave SSISlave; + +/* Slave devices. */ +typedef struct { + void (*init)(SSISlave *dev); + uint32_t (*transfer)(SSISlave *dev, uint32_t val); +} SSISlaveInfo; + +struct SSISlave { + DeviceState qdev; + SSISlaveInfo *info; +}; + +#define SSI_SLAVE_FROM_QDEV(dev) DO_UPCAST(SSISlave, qdev, dev) +#define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev) + +void ssi_register_slave(const char *name, int size, SSISlaveInfo *info); + +DeviceState *ssi_create_slave(SSIBus *bus, const char *name); + +/* Master interface. */ +SSIBus *ssi_create_bus(void); + +uint32_t ssi_transfer(SSIBus *bus, uint32_t val); + +#endif diff --git a/qemu-common.h b/qemu-common.h index 9d644b68b..fdc367997 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -183,6 +183,7 @@ typedef struct MouseTransformInfo MouseTransformInfo; typedef struct uWireSlave uWireSlave; typedef struct I2SCodec I2SCodec; typedef struct DeviceState DeviceState; +typedef struct SSIBus SSIBus; /* CPU save/load. */ void cpu_save(QEMUFile *f, void *opaque); |