Lines Matching +full:i2c +full:- +full:0

2  * PPC4xx I2C controller emulation
8 * Copyright (c) 2016-2018 BALATON Zoltan
32 #include "hw/i2c/ppc4xx_i2c.h"
38 IIC_MDBUF = 0,
56 #define IIC_CNTL_PT (1 << 0)
67 #define IIC_STS_PT (1 << 0)
73 #define IIC_EXTSTS_XFRA (1 << 0)
77 #define IIC_INTRMSK_EIMTC (1 << 0)
82 #define IIC_XTCNTLSS_SRST (1 << 0)
87 #define IIC_DIRECTCNTL_MSCL (1 << 0)
91 PPC4xxI2CState *i2c = PPC4xx_I2C(s); in ppc4xx_i2c_reset() local
93 i2c->mdidx = -1; in ppc4xx_i2c_reset()
94 memset(i2c->mdata, 0, ARRAY_SIZE(i2c->mdata)); in ppc4xx_i2c_reset()
96 i2c->cntl = 0; in ppc4xx_i2c_reset()
97 i2c->mdcntl = 0; in ppc4xx_i2c_reset()
98 i2c->sts = 0; in ppc4xx_i2c_reset()
99 i2c->extsts = IIC_EXTSTS_BCS_FREE; in ppc4xx_i2c_reset()
100 i2c->clkdiv = 0; in ppc4xx_i2c_reset()
101 i2c->intrmsk = 0; in ppc4xx_i2c_reset()
102 i2c->xfrcnt = 0; in ppc4xx_i2c_reset()
103 i2c->xtcntlss = 0; in ppc4xx_i2c_reset()
104 i2c->directcntl = 0xf; /* all non-reserved bits set */ in ppc4xx_i2c_reset()
109 PPC4xxI2CState *i2c = PPC4xx_I2C(opaque); in ppc4xx_i2c_readb() local
115 if (i2c->mdidx < 0) { in ppc4xx_i2c_readb()
116 ret = 0xff; in ppc4xx_i2c_readb()
119 ret = i2c->mdata[0]; in ppc4xx_i2c_readb()
120 if (i2c->mdidx == 3) { in ppc4xx_i2c_readb()
121 i2c->sts &= ~IIC_STS_MDBF; in ppc4xx_i2c_readb()
122 } else if (i2c->mdidx == 0) { in ppc4xx_i2c_readb()
123 i2c->sts &= ~IIC_STS_MDBS; in ppc4xx_i2c_readb()
125 for (i = 0; i < i2c->mdidx; i++) { in ppc4xx_i2c_readb()
126 i2c->mdata[i] = i2c->mdata[i + 1]; in ppc4xx_i2c_readb()
128 if (i2c->mdidx >= 0) { in ppc4xx_i2c_readb()
129 i2c->mdidx--; in ppc4xx_i2c_readb()
133 ret = i2c->lmadr; in ppc4xx_i2c_readb()
136 ret = i2c->hmadr; in ppc4xx_i2c_readb()
139 ret = i2c->cntl; in ppc4xx_i2c_readb()
142 ret = i2c->mdcntl; in ppc4xx_i2c_readb()
145 ret = i2c->sts; in ppc4xx_i2c_readb()
148 ret = i2c_bus_busy(i2c->bus) ? in ppc4xx_i2c_readb()
152 ret = i2c->lsadr; in ppc4xx_i2c_readb()
155 ret = i2c->hsadr; in ppc4xx_i2c_readb()
158 ret = i2c->clkdiv; in ppc4xx_i2c_readb()
161 ret = i2c->intrmsk; in ppc4xx_i2c_readb()
164 ret = i2c->xfrcnt; in ppc4xx_i2c_readb()
167 ret = i2c->xtcntlss; in ppc4xx_i2c_readb()
170 ret = i2c->directcntl; in ppc4xx_i2c_readb()
174 qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register 0x%" in ppc4xx_i2c_readb()
177 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%" in ppc4xx_i2c_readb()
180 ret = 0; in ppc4xx_i2c_readb()
189 PPC4xxI2CState *i2c = opaque; in ppc4xx_i2c_writeb() local
193 if (i2c->mdidx >= 3) { in ppc4xx_i2c_writeb()
196 i2c->mdata[++i2c->mdidx] = value; in ppc4xx_i2c_writeb()
197 if (i2c->mdidx == 3) { in ppc4xx_i2c_writeb()
198 i2c->sts |= IIC_STS_MDBF; in ppc4xx_i2c_writeb()
199 } else if (i2c->mdidx == 0) { in ppc4xx_i2c_writeb()
200 i2c->sts |= IIC_STS_MDBS; in ppc4xx_i2c_writeb()
204 i2c->lmadr = value; in ppc4xx_i2c_writeb()
207 i2c->hmadr = value; in ppc4xx_i2c_writeb()
210 i2c->cntl = value & ~IIC_CNTL_PT; in ppc4xx_i2c_writeb()
215 if (value & IIC_CNTL_HMT && i2c_bus_busy(i2c->bus)) { in ppc4xx_i2c_writeb()
216 i2c_end_transfer(i2c->bus); in ppc4xx_i2c_writeb()
217 if (i2c->mdcntl & IIC_MDCNTL_EINT && in ppc4xx_i2c_writeb()
218 i2c->intrmsk & IIC_INTRMSK_EIHE) { in ppc4xx_i2c_writeb()
219 i2c->sts |= IIC_STS_IRQA; in ppc4xx_i2c_writeb()
220 qemu_irq_raise(i2c->irq); in ppc4xx_i2c_writeb()
227 if (recv && (i2c->lmadr >> 1) >= 0x50 && (i2c->lmadr >> 1) < 0x58) { in ppc4xx_i2c_writeb()
232 for (i = 0; i <= tct; i++) { in ppc4xx_i2c_writeb()
233 if (!i2c_bus_busy(i2c->bus)) { in ppc4xx_i2c_writeb()
234 i2c->extsts = IIC_EXTSTS_BCS_FREE; in ppc4xx_i2c_writeb()
235 if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, recv)) { in ppc4xx_i2c_writeb()
236 i2c->sts |= IIC_STS_ERR; in ppc4xx_i2c_writeb()
237 i2c->extsts |= IIC_EXTSTS_XFRA; in ppc4xx_i2c_writeb()
240 i2c->sts &= ~IIC_STS_ERR; in ppc4xx_i2c_writeb()
243 if (!(i2c->sts & IIC_STS_ERR)) { in ppc4xx_i2c_writeb()
245 i2c->mdata[i] = i2c_recv(i2c->bus); in ppc4xx_i2c_writeb()
246 } else if (i2c_send(i2c->bus, i2c->mdata[i]) < 0) { in ppc4xx_i2c_writeb()
247 i2c->sts |= IIC_STS_ERR; in ppc4xx_i2c_writeb()
248 i2c->extsts |= IIC_EXTSTS_XFRA; in ppc4xx_i2c_writeb()
253 i2c_end_transfer(i2c->bus); in ppc4xx_i2c_writeb()
256 i2c->xfrcnt = i; in ppc4xx_i2c_writeb()
257 i2c->mdidx = i - 1; in ppc4xx_i2c_writeb()
258 if (recv && i2c->mdidx >= 0) { in ppc4xx_i2c_writeb()
259 i2c->sts |= IIC_STS_MDBS; in ppc4xx_i2c_writeb()
261 if (recv && i2c->mdidx == 3) { in ppc4xx_i2c_writeb()
262 i2c->sts |= IIC_STS_MDBF; in ppc4xx_i2c_writeb()
264 if (i && i2c->mdcntl & IIC_MDCNTL_EINT && in ppc4xx_i2c_writeb()
265 i2c->intrmsk & IIC_INTRMSK_EIMTC) { in ppc4xx_i2c_writeb()
266 i2c->sts |= IIC_STS_IRQA; in ppc4xx_i2c_writeb()
267 qemu_irq_raise(i2c->irq); in ppc4xx_i2c_writeb()
272 i2c->mdcntl = value & 0x3d; in ppc4xx_i2c_writeb()
278 i2c->mdidx = -1; in ppc4xx_i2c_writeb()
279 memset(i2c->mdata, 0, ARRAY_SIZE(i2c->mdata)); in ppc4xx_i2c_writeb()
280 i2c->sts &= ~(IIC_STS_MDBF | IIC_STS_MDBS); in ppc4xx_i2c_writeb()
284 i2c->sts &= ~(value & 0x0a); in ppc4xx_i2c_writeb()
285 if (value & IIC_STS_IRQA && i2c->mdcntl & IIC_MDCNTL_EINT) { in ppc4xx_i2c_writeb()
286 qemu_irq_lower(i2c->irq); in ppc4xx_i2c_writeb()
290 i2c->extsts &= ~(value & 0x8f); in ppc4xx_i2c_writeb()
293 i2c->lsadr = value; in ppc4xx_i2c_writeb()
296 i2c->hsadr = value; in ppc4xx_i2c_writeb()
299 i2c->clkdiv = value; in ppc4xx_i2c_writeb()
302 i2c->intrmsk = value; in ppc4xx_i2c_writeb()
305 i2c->xfrcnt = value & 0x77; in ppc4xx_i2c_writeb()
308 i2c->xtcntlss &= ~(value & 0xf0); in ppc4xx_i2c_writeb()
310 /* Is it actually a full reset? U-Boot sets some regs before */ in ppc4xx_i2c_writeb()
311 ppc4xx_i2c_reset(DEVICE(i2c)); in ppc4xx_i2c_writeb()
316 i2c->directcntl = value & (IIC_DIRECTCNTL_SDAC & IIC_DIRECTCNTL_SCLC); in ppc4xx_i2c_writeb()
317 i2c->directcntl |= (value & IIC_DIRECTCNTL_SCLC ? 1 : 0); in ppc4xx_i2c_writeb()
318 bitbang_i2c_set(&i2c->bitbang, BITBANG_I2C_SCL, in ppc4xx_i2c_writeb()
319 i2c->directcntl & IIC_DIRECTCNTL_MSCL); in ppc4xx_i2c_writeb()
320 i2c->directcntl |= bitbang_i2c_set(&i2c->bitbang, BITBANG_I2C_SDA, in ppc4xx_i2c_writeb()
321 (value & IIC_DIRECTCNTL_SDAC) != 0) << 1; in ppc4xx_i2c_writeb()
325 qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register 0x%" in ppc4xx_i2c_writeb()
328 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%" in ppc4xx_i2c_writeb()
349 memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s, in ppc4xx_i2c_init()
351 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); in ppc4xx_i2c_init()
352 sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); in ppc4xx_i2c_init()
353 s->bus = i2c_init_bus(DEVICE(s), "i2c"); in ppc4xx_i2c_init()
354 bitbang_i2c_init(&s->bitbang, s->bus); in ppc4xx_i2c_init()