diff options
author | BALATON Zoltan | 2018-06-19 10:52:15 +0200 |
---|---|---|
committer | David Gibson | 2018-06-21 13:22:53 +0200 |
commit | ef9173a5c086b5114343a86943f9b26a9c72d7d6 (patch) | |
tree | 345b7ca3c115f2a6caad566f2af04be1439cbb48 /hw/i2c/ppc4xx_i2c.c | |
parent | ppc4xx_i2c: Remove unimplemented sdata and intr registers (diff) | |
download | qemu-ef9173a5c086b5114343a86943f9b26a9c72d7d6.tar.gz qemu-ef9173a5c086b5114343a86943f9b26a9c72d7d6.tar.xz qemu-ef9173a5c086b5114343a86943f9b26a9c72d7d6.zip |
ppc4xx_i2c: Implement directcntl register
As well as being able to generate its own i2c transactions, the ppc4xx
i2c controller has a DIRECTCNTL register which allows explicit control
of the i2c lines.
Using this register an OS can directly bitbang i2c operations. In
order to let emulated i2c devices respond to this, we need to wire up
the DIRECTCNTL register to qemu's bitbanged i2c handling code.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/i2c/ppc4xx_i2c.c')
-rw-r--r-- | hw/i2c/ppc4xx_i2c.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/hw/i2c/ppc4xx_i2c.c b/hw/i2c/ppc4xx_i2c.c index 4e0aaae1fc..fca80d695a 100644 --- a/hw/i2c/ppc4xx_i2c.c +++ b/hw/i2c/ppc4xx_i2c.c @@ -30,6 +30,7 @@ #include "cpu.h" #include "hw/hw.h" #include "hw/i2c/ppc4xx_i2c.h" +#include "bitbang_i2c.h" #define PPC4xx_I2C_MEM_SIZE 18 @@ -46,6 +47,11 @@ #define IIC_XTCNTLSS_SRST (1 << 0) +#define IIC_DIRECTCNTL_SDAC (1 << 3) +#define IIC_DIRECTCNTL_SCLC (1 << 2) +#define IIC_DIRECTCNTL_MSDA (1 << 1) +#define IIC_DIRECTCNTL_MSCL (1 << 0) + static void ppc4xx_i2c_reset(DeviceState *s) { PPC4xxI2CState *i2c = PPC4xx_I2C(s); @@ -289,7 +295,12 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value, i2c->xtcntlss = value; break; case 16: - i2c->directcntl = value & 0x7; + i2c->directcntl = value & (IIC_DIRECTCNTL_SDAC & IIC_DIRECTCNTL_SCLC); + i2c->directcntl |= (value & IIC_DIRECTCNTL_SCLC ? 1 : 0); + bitbang_i2c_set(i2c->bitbang, BITBANG_I2C_SCL, + i2c->directcntl & IIC_DIRECTCNTL_MSCL); + i2c->directcntl |= bitbang_i2c_set(i2c->bitbang, BITBANG_I2C_SDA, + (value & IIC_DIRECTCNTL_SDAC) != 0) << 1; break; default: if (addr < PPC4xx_I2C_MEM_SIZE) { @@ -322,6 +333,7 @@ static void ppc4xx_i2c_init(Object *o) sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); s->bus = i2c_init_bus(DEVICE(s), "i2c"); + s->bitbang = bitbang_i2c_init(s->bus); } static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data) |