diff options
Diffstat (limited to 'hw/pxa2xx.c')
-rw-r--r-- | hw/pxa2xx.c | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index 016716384a..b1ffa9f8ff 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) |