X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=hw%2Fomap_i2c.c;h=20bc82e3b817c9d4d69c6ead6e9a26f38d73328f;hb=050a46065de8e3d4ee5a04f5598d666f63d34800;hp=d7c18882dacdd407798cdfef345b1d6b7a5840a2;hpb=3737c0541a8fa0afe492cc95453840c90cc7eb77;p=qemu.git diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c index d7c18882d..20bc82e3b 100644 --- a/hw/omap_i2c.c +++ b/hw/omap_i2c.c @@ -19,13 +19,20 @@ #include "hw.h" #include "i2c.h" #include "omap.h" +#include "sysbus.h" -struct omap_i2c_s { + +typedef struct OMAPI2CState { + SysBusDevice busdev; + MemoryRegion iomem; qemu_irq irq; qemu_irq drq[2]; i2c_bus *bus; uint8_t revision; + void *iclk; + void *fclk; + uint8_t mask; uint16_t stat; uint16_t dma; @@ -39,12 +46,12 @@ struct omap_i2c_s { uint8_t divider; uint8_t times[2]; uint16_t test; -}; +} OMAPI2CState; #define OMAP2_INTR_REV 0x34 #define OMAP2_GC_REV 0x34 -static void omap_i2c_interrupts_update(struct omap_i2c_s *s) +static void omap_i2c_interrupts_update(OMAPI2CState *s) { qemu_set_irq(s->irq, s->stat & s->mask); if ((s->dma >> 15) & 1) /* RDMA_EN */ @@ -53,7 +60,7 @@ static void omap_i2c_interrupts_update(struct omap_i2c_s *s) qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */ } -static void omap_i2c_fifo_run(struct omap_i2c_s *s) +static void omap_i2c_fifo_run(OMAPI2CState *s) { int ack = 1; @@ -121,8 +128,10 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s) s->control &= ~(1 << 1); /* STP */ } -void omap_i2c_reset(struct omap_i2c_s *s) +static void omap_i2c_reset(DeviceState *dev) { + OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, + sysbus_from_qdev(dev)); s->mask = 0; s->stat = 0; s->dma = 0; @@ -142,7 +151,7 @@ void omap_i2c_reset(struct omap_i2c_s *s) static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr) { - struct omap_i2c_s *s = (struct omap_i2c_s *) opaque; + OMAPI2CState *s = opaque; int offset = addr & OMAP_MPUI_REG_MASK; uint16_t ret; @@ -190,8 +199,9 @@ static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr) if (s->rxlen > 2) s->fifo >>= 16; s->rxlen -= 2; - } else - /* XXX: remote access (qualifier) error - what's that? */; + } else { + /* XXX: remote access (qualifier) error - what's that? */ + } if (!s->rxlen) { s->stat &= ~(1 << 3); /* RRDY */ if (((s->control >> 10) & 1) && /* MST */ @@ -241,7 +251,7 @@ static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr) static void omap_i2c_write(void *opaque, target_phys_addr_t addr, uint32_t value) { - struct omap_i2c_s *s = (struct omap_i2c_s *) opaque; + OMAPI2CState *s = opaque; int offset = addr & OMAP_MPUI_REG_MASK; int nack; @@ -307,14 +317,14 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr, } if (value & 2) - omap_i2c_reset(s); + omap_i2c_reset(&s->busdev.qdev); break; case 0x24: /* I2C_CON */ s->control = value & 0xcf87; if (~value & (1 << 15)) { /* I2C_EN */ if (s->revision < OMAP2_INTR_REV) - omap_i2c_reset(s); + omap_i2c_reset(&s->busdev.qdev); break; } if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */ @@ -383,7 +393,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr, static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) { - struct omap_i2c_s *s = (struct omap_i2c_s *) opaque; + OMAPI2CState *s = opaque; int offset = addr & OMAP_MPUI_REG_MASK; switch (offset) { @@ -408,62 +418,75 @@ static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr, } } -static CPUReadMemoryFunc * const omap_i2c_readfn[] = { - omap_badwidth_read16, - omap_i2c_read, - omap_badwidth_read16, +static const MemoryRegionOps omap_i2c_ops = { + .old_mmio = { + .read = { + omap_badwidth_read16, + omap_i2c_read, + omap_badwidth_read16, + }, + .write = { + omap_i2c_writeb, /* Only the last fifo write can be 8 bit. */ + omap_i2c_write, + omap_badwidth_write16, + }, + }, + .endianness = DEVICE_NATIVE_ENDIAN, }; -static CPUWriteMemoryFunc * const omap_i2c_writefn[] = { - omap_i2c_writeb, /* Only the last fifo write can be 8 bit. */ - omap_i2c_write, - omap_badwidth_write16, +static int omap_i2c_init(SysBusDevice *dev) +{ + OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, dev); + + if (!s->fclk) { + hw_error("omap_i2c: fclk not connected\n"); + } + if (s->revision >= OMAP2_INTR_REV && !s->iclk) { + /* Note that OMAP1 doesn't have a separate interface clock */ + hw_error("omap_i2c: iclk not connected\n"); + } + sysbus_init_irq(dev, &s->irq); + sysbus_init_irq(dev, &s->drq[0]); + sysbus_init_irq(dev, &s->drq[1]); + memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c", + (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000); + sysbus_init_mmio(dev, &s->iomem); + s->bus = i2c_init_bus(&dev->qdev, NULL); + return 0; +} + +static Property omap_i2c_properties[] = { + DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0), + DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk), + DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk), + DEFINE_PROP_END_OF_LIST(), }; -struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base, - qemu_irq irq, qemu_irq *dma, omap_clk clk) +static void omap_i2c_class_init(ObjectClass *klass, void *data) { - int iomemtype; - struct omap_i2c_s *s = (struct omap_i2c_s *) - qemu_mallocz(sizeof(struct omap_i2c_s)); - - /* TODO: set a value greater or equal to real hardware */ - s->revision = 0x11; - s->irq = irq; - s->drq[0] = dma[0]; - s->drq[1] = dma[1]; - s->bus = i2c_init_bus(NULL, "i2c"); - omap_i2c_reset(s); - - iomemtype = cpu_register_io_memory(omap_i2c_readfn, - omap_i2c_writefn, s); - cpu_register_physical_memory(base, 0x800, iomemtype); - - return s; + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + k->init = omap_i2c_init; + dc->props = omap_i2c_properties; + dc->reset = omap_i2c_reset; } -struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta, - qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk) +static TypeInfo omap_i2c_info = { + .name = "omap_i2c", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(OMAPI2CState), + .class_init = omap_i2c_class_init, +}; + +static void omap_i2c_register_types(void) { - int iomemtype; - struct omap_i2c_s *s = (struct omap_i2c_s *) - qemu_mallocz(sizeof(struct omap_i2c_s)); - - s->revision = 0x34; - s->irq = irq; - s->drq[0] = dma[0]; - s->drq[1] = dma[1]; - s->bus = i2c_init_bus(NULL, "i2c"); - omap_i2c_reset(s); - - iomemtype = l4_register_io_memory(omap_i2c_readfn, - omap_i2c_writefn, s); - omap_l4_attach(ta, 0, iomemtype); - - return s; + type_register_static(&omap_i2c_info); } -i2c_bus *omap_i2c_bus(struct omap_i2c_s *s) +i2c_bus *omap_i2c_bus(DeviceState *omap_i2c) { + OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, sysbus_from_qdev(omap_i2c)); return s->bus; } + +type_init(omap_i2c_register_types)