1 | /* |
2 | * PPC4xx I2C controller emulation |
3 | * |
4 | * Copyright (c) 2007 Jocelyn Mayer |
5 | * Copyright (c) 2012 François Revol |
6 | * Copyright (c) 2016-2018 BALATON Zoltan |
7 | * |
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
9 | * of this software and associated documentation files (the "Software"), to deal |
10 | * in the Software without restriction, including without limitation the rights |
11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
12 | * copies of the Software, and to permit persons to whom the Software is |
13 | * furnished to do so, subject to the following conditions: |
14 | * |
15 | * The above copyright notice and this permission notice shall be included in |
16 | * all copies or substantial portions of the Software. |
17 | * |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
24 | * THE SOFTWARE. |
25 | */ |
26 | |
27 | #include "qemu/osdep.h" |
28 | #include "qemu/log.h" |
29 | #include "qemu/module.h" |
30 | #include "cpu.h" |
31 | #include "hw/i2c/ppc4xx_i2c.h" |
32 | #include "hw/irq.h" |
33 | |
34 | #define PPC4xx_I2C_MEM_SIZE 18 |
35 | |
36 | enum { |
37 | IIC_MDBUF = 0, |
38 | /* IIC_SDBUF = 2, */ |
39 | IIC_LMADR = 4, |
40 | IIC_HMADR, |
41 | IIC_CNTL, |
42 | IIC_MDCNTL, |
43 | IIC_STS, |
44 | IIC_EXTSTS, |
45 | IIC_LSADR, |
46 | IIC_HSADR, |
47 | IIC_CLKDIV, |
48 | IIC_INTRMSK, |
49 | IIC_XFRCNT, |
50 | IIC_XTCNTLSS, |
51 | IIC_DIRECTCNTL |
52 | /* IIC_INTR */ |
53 | }; |
54 | |
55 | #define IIC_CNTL_PT (1 << 0) |
56 | #define IIC_CNTL_READ (1 << 1) |
57 | #define IIC_CNTL_CHT (1 << 2) |
58 | #define IIC_CNTL_RPST (1 << 3) |
59 | #define IIC_CNTL_AMD (1 << 6) |
60 | #define IIC_CNTL_HMT (1 << 7) |
61 | |
62 | #define IIC_MDCNTL_EINT (1 << 2) |
63 | #define IIC_MDCNTL_ESM (1 << 3) |
64 | #define IIC_MDCNTL_FMDB (1 << 6) |
65 | |
66 | #define IIC_STS_PT (1 << 0) |
67 | #define IIC_STS_IRQA (1 << 1) |
68 | #define IIC_STS_ERR (1 << 2) |
69 | #define IIC_STS_MDBF (1 << 4) |
70 | #define IIC_STS_MDBS (1 << 5) |
71 | |
72 | #define IIC_EXTSTS_XFRA (1 << 0) |
73 | #define IIC_EXTSTS_BCS_FREE (4 << 4) |
74 | #define IIC_EXTSTS_BCS_BUSY (5 << 4) |
75 | |
76 | #define IIC_INTRMSK_EIMTC (1 << 0) |
77 | #define IIC_INTRMSK_EITA (1 << 1) |
78 | #define IIC_INTRMSK_EIIC (1 << 2) |
79 | #define IIC_INTRMSK_EIHE (1 << 3) |
80 | |
81 | #define IIC_XTCNTLSS_SRST (1 << 0) |
82 | |
83 | #define IIC_DIRECTCNTL_SDAC (1 << 3) |
84 | #define IIC_DIRECTCNTL_SCLC (1 << 2) |
85 | #define IIC_DIRECTCNTL_MSDA (1 << 1) |
86 | #define IIC_DIRECTCNTL_MSCL (1 << 0) |
87 | |
88 | static void ppc4xx_i2c_reset(DeviceState *s) |
89 | { |
90 | PPC4xxI2CState *i2c = PPC4xx_I2C(s); |
91 | |
92 | i2c->mdidx = -1; |
93 | memset(i2c->mdata, 0, ARRAY_SIZE(i2c->mdata)); |
94 | /* [hl][ms]addr are not affected by reset */ |
95 | i2c->cntl = 0; |
96 | i2c->mdcntl = 0; |
97 | i2c->sts = 0; |
98 | i2c->extsts = IIC_EXTSTS_BCS_FREE; |
99 | i2c->clkdiv = 0; |
100 | i2c->intrmsk = 0; |
101 | i2c->xfrcnt = 0; |
102 | i2c->xtcntlss = 0; |
103 | i2c->directcntl = 0xf; /* all non-reserved bits set */ |
104 | } |
105 | |
106 | static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size) |
107 | { |
108 | PPC4xxI2CState *i2c = PPC4xx_I2C(opaque); |
109 | uint64_t ret; |
110 | int i; |
111 | |
112 | switch (addr) { |
113 | case IIC_MDBUF: |
114 | if (i2c->mdidx < 0) { |
115 | ret = 0xff; |
116 | break; |
117 | } |
118 | ret = i2c->mdata[0]; |
119 | if (i2c->mdidx == 3) { |
120 | i2c->sts &= ~IIC_STS_MDBF; |
121 | } else if (i2c->mdidx == 0) { |
122 | i2c->sts &= ~IIC_STS_MDBS; |
123 | } |
124 | for (i = 0; i < i2c->mdidx; i++) { |
125 | i2c->mdata[i] = i2c->mdata[i + 1]; |
126 | } |
127 | if (i2c->mdidx >= 0) { |
128 | i2c->mdidx--; |
129 | } |
130 | break; |
131 | case IIC_LMADR: |
132 | ret = i2c->lmadr; |
133 | break; |
134 | case IIC_HMADR: |
135 | ret = i2c->hmadr; |
136 | break; |
137 | case IIC_CNTL: |
138 | ret = i2c->cntl; |
139 | break; |
140 | case IIC_MDCNTL: |
141 | ret = i2c->mdcntl; |
142 | break; |
143 | case IIC_STS: |
144 | ret = i2c->sts; |
145 | break; |
146 | case IIC_EXTSTS: |
147 | ret = i2c_bus_busy(i2c->bus) ? |
148 | IIC_EXTSTS_BCS_BUSY : IIC_EXTSTS_BCS_FREE; |
149 | break; |
150 | case IIC_LSADR: |
151 | ret = i2c->lsadr; |
152 | break; |
153 | case IIC_HSADR: |
154 | ret = i2c->hsadr; |
155 | break; |
156 | case IIC_CLKDIV: |
157 | ret = i2c->clkdiv; |
158 | break; |
159 | case IIC_INTRMSK: |
160 | ret = i2c->intrmsk; |
161 | break; |
162 | case IIC_XFRCNT: |
163 | ret = i2c->xfrcnt; |
164 | break; |
165 | case IIC_XTCNTLSS: |
166 | ret = i2c->xtcntlss; |
167 | break; |
168 | case IIC_DIRECTCNTL: |
169 | ret = i2c->directcntl; |
170 | break; |
171 | default: |
172 | if (addr < PPC4xx_I2C_MEM_SIZE) { |
173 | qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register 0x%" |
174 | HWADDR_PRIx "\n" , __func__, addr); |
175 | } else { |
176 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%" |
177 | HWADDR_PRIx "\n" , __func__, addr); |
178 | } |
179 | ret = 0; |
180 | break; |
181 | } |
182 | return ret; |
183 | } |
184 | |
185 | static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value, |
186 | unsigned int size) |
187 | { |
188 | PPC4xxI2CState *i2c = opaque; |
189 | |
190 | switch (addr) { |
191 | case IIC_MDBUF: |
192 | if (i2c->mdidx >= 3) { |
193 | break; |
194 | } |
195 | i2c->mdata[++i2c->mdidx] = value; |
196 | if (i2c->mdidx == 3) { |
197 | i2c->sts |= IIC_STS_MDBF; |
198 | } else if (i2c->mdidx == 0) { |
199 | i2c->sts |= IIC_STS_MDBS; |
200 | } |
201 | break; |
202 | case IIC_LMADR: |
203 | i2c->lmadr = value; |
204 | break; |
205 | case IIC_HMADR: |
206 | i2c->hmadr = value; |
207 | break; |
208 | case IIC_CNTL: |
209 | i2c->cntl = value & ~IIC_CNTL_PT; |
210 | if (value & IIC_CNTL_AMD) { |
211 | qemu_log_mask(LOG_UNIMP, "%s: only 7 bit addresses supported\n" , |
212 | __func__); |
213 | } |
214 | if (value & IIC_CNTL_HMT && i2c_bus_busy(i2c->bus)) { |
215 | i2c_end_transfer(i2c->bus); |
216 | if (i2c->mdcntl & IIC_MDCNTL_EINT && |
217 | i2c->intrmsk & IIC_INTRMSK_EIHE) { |
218 | i2c->sts |= IIC_STS_IRQA; |
219 | qemu_irq_raise(i2c->irq); |
220 | } |
221 | } else if (value & IIC_CNTL_PT) { |
222 | int recv = (value & IIC_CNTL_READ) >> 1; |
223 | int tct = value >> 4 & 3; |
224 | int i; |
225 | |
226 | if (recv && (i2c->lmadr >> 1) >= 0x50 && (i2c->lmadr >> 1) < 0x58) { |
227 | /* smbus emulation does not like multi byte reads w/o restart */ |
228 | value |= IIC_CNTL_RPST; |
229 | } |
230 | |
231 | for (i = 0; i <= tct; i++) { |
232 | if (!i2c_bus_busy(i2c->bus)) { |
233 | i2c->extsts = IIC_EXTSTS_BCS_FREE; |
234 | if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, recv)) { |
235 | i2c->sts |= IIC_STS_ERR; |
236 | i2c->extsts |= IIC_EXTSTS_XFRA; |
237 | break; |
238 | } else { |
239 | i2c->sts &= ~IIC_STS_ERR; |
240 | } |
241 | } |
242 | if (!(i2c->sts & IIC_STS_ERR) && |
243 | i2c_send_recv(i2c->bus, &i2c->mdata[i], !recv)) { |
244 | i2c->sts |= IIC_STS_ERR; |
245 | i2c->extsts |= IIC_EXTSTS_XFRA; |
246 | break; |
247 | } |
248 | if (value & IIC_CNTL_RPST || !(value & IIC_CNTL_CHT)) { |
249 | i2c_end_transfer(i2c->bus); |
250 | } |
251 | } |
252 | i2c->xfrcnt = i; |
253 | i2c->mdidx = i - 1; |
254 | if (recv && i2c->mdidx >= 0) { |
255 | i2c->sts |= IIC_STS_MDBS; |
256 | } |
257 | if (recv && i2c->mdidx == 3) { |
258 | i2c->sts |= IIC_STS_MDBF; |
259 | } |
260 | if (i && i2c->mdcntl & IIC_MDCNTL_EINT && |
261 | i2c->intrmsk & IIC_INTRMSK_EIMTC) { |
262 | i2c->sts |= IIC_STS_IRQA; |
263 | qemu_irq_raise(i2c->irq); |
264 | } |
265 | } |
266 | break; |
267 | case IIC_MDCNTL: |
268 | i2c->mdcntl = value & 0x3d; |
269 | if (value & IIC_MDCNTL_ESM) { |
270 | qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n" , |
271 | __func__); |
272 | } |
273 | if (value & IIC_MDCNTL_FMDB) { |
274 | i2c->mdidx = -1; |
275 | memset(i2c->mdata, 0, ARRAY_SIZE(i2c->mdata)); |
276 | i2c->sts &= ~(IIC_STS_MDBF | IIC_STS_MDBS); |
277 | } |
278 | break; |
279 | case IIC_STS: |
280 | i2c->sts &= ~(value & 0x0a); |
281 | if (value & IIC_STS_IRQA && i2c->mdcntl & IIC_MDCNTL_EINT) { |
282 | qemu_irq_lower(i2c->irq); |
283 | } |
284 | break; |
285 | case IIC_EXTSTS: |
286 | i2c->extsts &= ~(value & 0x8f); |
287 | break; |
288 | case IIC_LSADR: |
289 | i2c->lsadr = value; |
290 | break; |
291 | case IIC_HSADR: |
292 | i2c->hsadr = value; |
293 | break; |
294 | case IIC_CLKDIV: |
295 | i2c->clkdiv = value; |
296 | break; |
297 | case IIC_INTRMSK: |
298 | i2c->intrmsk = value; |
299 | break; |
300 | case IIC_XFRCNT: |
301 | i2c->xfrcnt = value & 0x77; |
302 | break; |
303 | case IIC_XTCNTLSS: |
304 | i2c->xtcntlss &= ~(value & 0xf0); |
305 | if (value & IIC_XTCNTLSS_SRST) { |
306 | /* Is it actually a full reset? U-Boot sets some regs before */ |
307 | ppc4xx_i2c_reset(DEVICE(i2c)); |
308 | break; |
309 | } |
310 | break; |
311 | case IIC_DIRECTCNTL: |
312 | i2c->directcntl = value & (IIC_DIRECTCNTL_SDAC & IIC_DIRECTCNTL_SCLC); |
313 | i2c->directcntl |= (value & IIC_DIRECTCNTL_SCLC ? 1 : 0); |
314 | bitbang_i2c_set(&i2c->bitbang, BITBANG_I2C_SCL, |
315 | i2c->directcntl & IIC_DIRECTCNTL_MSCL); |
316 | i2c->directcntl |= bitbang_i2c_set(&i2c->bitbang, BITBANG_I2C_SDA, |
317 | (value & IIC_DIRECTCNTL_SDAC) != 0) << 1; |
318 | break; |
319 | default: |
320 | if (addr < PPC4xx_I2C_MEM_SIZE) { |
321 | qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register 0x%" |
322 | HWADDR_PRIx "\n" , __func__, addr); |
323 | } else { |
324 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%" |
325 | HWADDR_PRIx "\n" , __func__, addr); |
326 | } |
327 | break; |
328 | } |
329 | } |
330 | |
331 | static const MemoryRegionOps ppc4xx_i2c_ops = { |
332 | .read = ppc4xx_i2c_readb, |
333 | .write = ppc4xx_i2c_writeb, |
334 | .valid.min_access_size = 1, |
335 | .valid.max_access_size = 4, |
336 | .impl.min_access_size = 1, |
337 | .impl.max_access_size = 1, |
338 | .endianness = DEVICE_NATIVE_ENDIAN, |
339 | }; |
340 | |
341 | static void ppc4xx_i2c_init(Object *o) |
342 | { |
343 | PPC4xxI2CState *s = PPC4xx_I2C(o); |
344 | |
345 | memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s, |
346 | TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE); |
347 | sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); |
348 | sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); |
349 | s->bus = i2c_init_bus(DEVICE(s), "i2c" ); |
350 | bitbang_i2c_init(&s->bitbang, s->bus); |
351 | } |
352 | |
353 | static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data) |
354 | { |
355 | DeviceClass *dc = DEVICE_CLASS(klass); |
356 | |
357 | dc->reset = ppc4xx_i2c_reset; |
358 | } |
359 | |
360 | static const TypeInfo ppc4xx_i2c_type_info = { |
361 | .name = TYPE_PPC4xx_I2C, |
362 | .parent = TYPE_SYS_BUS_DEVICE, |
363 | .instance_size = sizeof(PPC4xxI2CState), |
364 | .instance_init = ppc4xx_i2c_init, |
365 | .class_init = ppc4xx_i2c_class_init, |
366 | }; |
367 | |
368 | static void ppc4xx_i2c_register_types(void) |
369 | { |
370 | type_register_static(&ppc4xx_i2c_type_info); |
371 | } |
372 | |
373 | type_init(ppc4xx_i2c_register_types) |
374 | |