aboutsummaryrefslogtreecommitdiff
path: root/hw/pxa2xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/pxa2xx.c')
-rw-r--r--hw/pxa2xx.c55
1 files changed, 42 insertions, 13 deletions
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 0167163..b1ffa9f 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1256,8 +1256,13 @@ static int pxa2xx_rtc_load(QEMUFile *f, void *opaque, int version_id)
}
/* I2C Interface */
+typedef struct {
+ i2c_slave i2c;
+ PXA2xxI2CState *host;
+} PXA2xxI2CSlaveState;
+
struct PXA2xxI2CState {
- i2c_slave slave;
+ PXA2xxI2CSlaveState *slave;
i2c_bus *bus;
qemu_irq irq;
target_phys_addr_t offset;
@@ -1287,7 +1292,8 @@ static void pxa2xx_i2c_update(PXA2xxI2CState *s)
/* These are only stubs now. */
static void pxa2xx_i2c_event(i2c_slave *i2c, enum i2c_event event)
{
- PXA2xxI2CState *s = (PXA2xxI2CState *) i2c;
+ PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
+ PXA2xxI2CState *s = slave->host;
switch (event) {
case I2C_START_SEND:
@@ -1310,7 +1316,8 @@ static void pxa2xx_i2c_event(i2c_slave *i2c, enum i2c_event event)
static int pxa2xx_i2c_rx(i2c_slave *i2c)
{
- PXA2xxI2CState *s = (PXA2xxI2CState *) i2c;
+ PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
+ PXA2xxI2CState *s = slave->host;
if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
return 0;
@@ -1324,7 +1331,8 @@ static int pxa2xx_i2c_rx(i2c_slave *i2c)
static int pxa2xx_i2c_tx(i2c_slave *i2c, uint8_t data)
{
- PXA2xxI2CState *s = (PXA2xxI2CState *) i2c;
+ PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
+ PXA2xxI2CState *s = slave->host;
if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
return 1;
@@ -1348,7 +1356,7 @@ static uint32_t pxa2xx_i2c_read(void *opaque, target_phys_addr_t addr)
case ISR:
return s->status | (i2c_bus_busy(s->bus) << 2);
case ISAR:
- return s->slave.address;
+ return s->slave->i2c.address;
case IDBR:
return s->data;
case IBMR:
@@ -1422,7 +1430,7 @@ static void pxa2xx_i2c_write(void *opaque, target_phys_addr_t addr,
break;
case ISAR:
- i2c_set_slave_address(&s->slave, value & 0x7f);
+ i2c_set_slave_address(&s->slave->i2c, value & 0x7f);
break;
case IDBR:
@@ -1455,7 +1463,7 @@ static void pxa2xx_i2c_save(QEMUFile *f, void *opaque)
qemu_put_8s(f, &s->ibmr);
qemu_put_8s(f, &s->data);
- i2c_slave_save(f, &s->slave);
+ i2c_slave_save(f, &s->slave->i2c);
}
static int pxa2xx_i2c_load(QEMUFile *f, void *opaque, int version_id)
@@ -1470,22 +1478,35 @@ static int pxa2xx_i2c_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_8s(f, &s->ibmr);
qemu_get_8s(f, &s->data);
- i2c_slave_load(f, &s->slave);
+ i2c_slave_load(f, &s->slave->i2c);
return 0;
}
+static void pxa2xx_i2c_slave_init(i2c_slave *i2c)
+{
+ /* Nothing to do. */
+}
+
+static I2CSlaveInfo pxa2xx_i2c_slave_info = {
+ .init = pxa2xx_i2c_slave_init,
+ .event = pxa2xx_i2c_event,
+ .recv = pxa2xx_i2c_rx,
+ .send = pxa2xx_i2c_tx
+};
+
PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
qemu_irq irq, uint32_t region_size)
{
int iomemtype;
+ DeviceState *dev;
+ PXA2xxI2CState *s = qemu_mallocz(sizeof(PXA2xxI2CState));
+
/* FIXME: Should the slave device really be on a separate bus? */
- PXA2xxI2CState *s = (PXA2xxI2CState *)
- i2c_slave_init(i2c_init_bus(), 0, sizeof(PXA2xxI2CState));
+ dev = i2c_create_slave(i2c_init_bus(), "pxa2xx-i2c-slave", 0);
+ s->slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, I2C_SLAVE_FROM_QDEV(dev));
+ s->slave->host = s;
s->irq = irq;
- s->slave.event = pxa2xx_i2c_event;
- s->slave.recv = pxa2xx_i2c_rx;
- s->slave.send = pxa2xx_i2c_tx;
s->bus = i2c_init_bus();
s->offset = base - (base & (~region_size) & TARGET_PAGE_MASK);
@@ -2257,3 +2278,11 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
pxa2xx_gpio_out_set(s->gpio, 1, s->reset);
return s;
}
+
+static void pxa2xx_register_devices(void)
+{
+ i2c_register_slave("pxa2xx-i2c-slave", sizeof(PXA2xxI2CSlaveState),
+ &pxa2xx_i2c_slave_info);
+}
+
+device_init(pxa2xx_register_devices)