1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include "hw.h"
22: #include "i2c.h"
23: #include "omap.h"
24:
25: struct omap_i2c_s {
26: target_phys_addr_t base;
27: qemu_irq irq;
28: qemu_irq drq[2];
29: i2c_slave slave;
30: i2c_bus *bus;
31:
32: uint8_t mask;
33: uint16_t stat;
34: uint16_t dma;
35: uint16_t count;
36: int count_cur;
37: uint32_t fifo;
38: int rxlen;
39: int txlen;
40: uint16_t control;
41: uint16_t addr[2];
42: uint8_t divider;
43: uint8_t times[2];
44: uint16_t test;
45: };
46:
47: static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
48: {
49: qemu_set_irq(s->irq, s->stat & s->mask);
50: if ((s->dma >> 15) & 1)
51: qemu_set_irq(s->drq[0], (s->stat >> 3) & 1);
52: if ((s->dma >> 7) & 1)
53: qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);
54: }
55:
56:
57: static void omap_i2c_event(i2c_slave *i2c, enum i2c_event event)
58: {
59: struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
60:
61: if ((~s->control >> 15) & 1)
62: return;
63:
64: switch (event) {
65: case I2C_START_SEND:
66: case I2C_START_RECV:
67: s->stat |= 1 << 9;
68: break;
69: case I2C_FINISH:
70: s->stat |= 1 << 2;
71: break;
72: case I2C_NACK:
73: s->stat |= 1 << 1;
74: break;
75: }
76:
77: omap_i2c_interrupts_update(s);
78: }
79:
80: static int omap_i2c_rx(i2c_slave *i2c)
81: {
82: struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
83: uint8_t ret = 0;
84:
85: if ((~s->control >> 15) & 1)
86: return -1;
87:
88: if (s->txlen)
89: ret = s->fifo >> ((-- s->txlen) << 3) & 0xff;
90: else
91: s->stat |= 1 << 10;
92: s->stat |= 1 << 4;
93:
94: omap_i2c_interrupts_update(s);
95: return ret;
96: }
97:
98: static int omap_i2c_tx(i2c_slave *i2c, uint8_t data)
99: {
100: struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
101:
102: if ((~s->control >> 15) & 1)
103: return 1;
104:
105: if (s->rxlen < 4)
106: s->fifo |= data << ((s->rxlen ++) << 3);
107: else
108: s->stat |= 1 << 11;
109: s->stat |= 1 << 3;
110:
111: omap_i2c_interrupts_update(s);
112: return 1;
113: }
114:
115: static void omap_i2c_fifo_run(struct omap_i2c_s *s)
116: {
117: int ack = 1;
118:
119: if (!i2c_bus_busy(s->bus))
120: return;
121:
122: if ((s->control >> 2) & 1) {
123: if ((s->control >> 1) & 1) {
124: i2c_end_transfer(s->bus);
125: s->control &= ~(1 << 1);
126: s->count_cur = s->count;
127: } else if ((s->control >> 9) & 1) {
128: while (ack && s->txlen)
129: ack = (i2c_send(s->bus,
130: (s->fifo >> ((-- s->txlen) << 3)) &
131: 0xff) >= 0);
132: s->stat |= 1 << 4;
133: } else {
134: while (s->rxlen < 4)
135: s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
136: s->stat |= 1 << 3;
137: }
138: } else {
139: if ((s->control >> 9) & 1) {
140: while (ack && s->count_cur && s->txlen) {
141: ack = (i2c_send(s->bus,
142: (s->fifo >> ((-- s->txlen) << 3)) &
143: 0xff) >= 0);
144: s->count_cur --;
145: }
146: if (ack && s->count_cur)
147: s->stat |= 1 << 4;
148: if (!s->count_cur) {
149: s->stat |= 1 << 2;
150: s->control &= ~(1 << 10);
151: }
152: } else {
153: while (s->count_cur && s->rxlen < 4) {
154: s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
155: s->count_cur --;
156: }
157: if (s->rxlen)
158: s->stat |= 1 << 3;
159: }
160: if (!s->count_cur) {
161: if ((s->control >> 1) & 1) {
162: i2c_end_transfer(s->bus);
163: s->control &= ~(1 << 1);
164: s->count_cur = s->count;
165: } else {
166: s->stat |= 1 << 2;
167: s->control &= ~(1 << 10);
168: }
169: }
170: }
171:
172: s->stat |= (!ack) << 1;
173: if (!ack)
174: s->control &= ~(1 << 1);
175: }
176:
177: void omap_i2c_reset(struct omap_i2c_s *s)
178: {
179: s->mask = 0;
180: s->stat = 0;
181: s->dma = 0;
182: s->count = 0;
183: s->count_cur = 0;
184: s->fifo = 0;
185: s->rxlen = 0;
186: s->txlen = 0;
187: s->control = 0;
188: s->addr[0] = 0;
189: s->addr[1] = 0;
190: s->divider = 0;
191: s->times[0] = 0;
192: s->times[1] = 0;
193: s->test = 0;
194: }
195:
196: static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
197: {
198: struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
199: int offset = addr & OMAP_MPUI_REG_MASK;
200: uint16_t ret;
201:
202: switch (offset) {
203: case 0x00:
204:
205: return 0x11;
206:
207: case 0x04:
208: return s->mask;
209:
210: case 0x08:
211: return s->stat | (i2c_bus_busy(s->bus) << 12);
212:
213: case 0x0c:
214: ret = ffs(s->stat & s->mask);
215: if (ret)
216: s->stat ^= 1 << (ret - 1);
217: omap_i2c_interrupts_update(s);
218: return ret;
219:
220: case 0x14:
221: return s->dma;
222:
223: case 0x18:
224: return s->count_cur;
225:
226: case 0x1c:
227: ret = 0;
228: if (s->control & (1 << 14)) {
229: ret |= ((s->fifo >> 0) & 0xff) << 8;
230: ret |= ((s->fifo >> 8) & 0xff) << 0;
231: } else {
232: ret |= ((s->fifo >> 8) & 0xff) << 8;
233: ret |= ((s->fifo >> 0) & 0xff) << 0;
234: }
235: if (s->rxlen == 1) {
236: s->stat |= 1 << 15;
237: s->rxlen = 0;
238: } else if (s->rxlen > 1) {
239: if (s->rxlen > 2)
240: s->fifo >>= 16;
241: s->rxlen -= 2;
242: } else
243: ;
244: if (!s->rxlen) {
245: s->stat |= ~(1 << 3);
246: if (((s->control >> 10) & 1) &&
247: ((~s->control >> 9) & 1)) {
248: s->stat |= 1 << 2;
249: s->control &= ~(1 << 10);
250: }
251: }
252: s->stat &= ~(1 << 11);
253: omap_i2c_fifo_run(s);
254: omap_i2c_interrupts_update(s);
255: return ret;
256:
257: case 0x24:
258: return s->control;
259:
260: case 0x28:
261: return s->addr[0];
262:
263: case 0x2c:
264: return s->addr[1];
265:
266: case 0x30:
267: return s->divider;
268:
269: case 0x34:
270: return s->times[0];
271:
272: case 0x38:
273: return s->times[1];
274:
275: case 0x3c:
276: if (s->test & (1 << 15)) {
277: s->test ^= 0xa;
278: return s->test;
279: } else
280: return s->test & ~0x300f;
281: }
282:
283: OMAP_BAD_REG(addr);
284: return 0;
285: }
286:
287: static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
288: uint32_t value)
289: {
290: struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
291: int offset = addr & OMAP_MPUI_REG_MASK;
292: int nack;
293:
294: switch (offset) {
295: case 0x00:
296: case 0x08:
297: case 0x0c:
298: OMAP_BAD_REG(addr);
299: return;
300:
301: case 0x04:
302: s->mask = value & 0x1f;
303: break;
304:
305: case 0x14:
306: s->dma = value & 0x8080;
307: if (value & (1 << 15))
308: s->mask &= ~(1 << 3);
309: if (value & (1 << 7))
310: s->mask &= ~(1 << 4);
311: break;
312:
313: case 0x18:
314: s->count = value;
315: break;
316:
317: case 0x1c:
318: if (s->txlen > 2) {
319:
320: break;
321: }
322: s->fifo <<= 16;
323: s->txlen += 2;
324: if (s->control & (1 << 14)) {
325: s->fifo |= ((value >> 8) & 0xff) << 8;
326: s->fifo |= ((value >> 0) & 0xff) << 0;
327: } else {
328: s->fifo |= ((value >> 0) & 0xff) << 8;
329: s->fifo |= ((value >> 8) & 0xff) << 0;
330: }
331: s->stat &= ~(1 << 10);
332: if (s->txlen > 2)
333: s->stat &= ~(1 << 4);
334: omap_i2c_fifo_run(s);
335: omap_i2c_interrupts_update(s);
336: break;
337:
338: case 0x24:
339: s->control = value & 0xcf07;
340: if (~value & (1 << 15)) {
341: omap_i2c_reset(s);
342: break;
343: }
344: if (~value & (1 << 10)) {
345: printf("%s: I^2C slave mode not supported\n", __FUNCTION__);
346: break;
347: }
348: if (value & (1 << 9)) {
349: printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__);
350: break;
351: }
352: if (value & (1 << 0)) {
353: nack = !!i2c_start_transfer(s->bus, s->addr[1],
354: (~value >> 9) & 1);
355: s->stat |= nack << 1;
356: s->control &= ~(1 << 0);
357: if (nack)
358: s->control &= ~(1 << 1);
359: else
360: omap_i2c_fifo_run(s);
361: omap_i2c_interrupts_update(s);
362: }
363: break;
364:
365: case 0x28:
366: s->addr[0] = value & 0x3ff;
367: i2c_set_slave_address(&s->slave, value & 0x7f);
368: break;
369:
370: case 0x2c:
371: s->addr[1] = value & 0x3ff;
372: break;
373:
374: case 0x30:
375: s->divider = value;
376: break;
377:
378: case 0x34:
379: s->times[0] = value;
380: break;
381:
382: case 0x38:
383: s->times[1] = value;
384: break;
385:
386: case 0x3c:
387: s->test = value & 0xf00f;
388: if (value & (1 << 15))
389: printf("%s: System Test not supported\n", __FUNCTION__);
390: break;
391:
392: default:
393: OMAP_BAD_REG(addr);
394: return;
395: }
396: }
397:
398: static CPUReadMemoryFunc *omap_i2c_readfn[] = {
399: omap_badwidth_read16,
400: omap_i2c_read,
401: omap_badwidth_read16,
402: };
403:
404: static CPUWriteMemoryFunc *omap_i2c_writefn[] = {
405: omap_badwidth_write16,
406: omap_i2c_write,
407: omap_i2c_write,
408: };
409:
410: struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
411: qemu_irq irq, qemu_irq *dma, omap_clk clk)
412: {
413: int iomemtype;
414: struct omap_i2c_s *s = (struct omap_i2c_s *)
415: qemu_mallocz(sizeof(struct omap_i2c_s));
416:
417: s->base = base;
418: s->irq = irq;
419: s->drq[0] = dma[0];
420: s->drq[1] = dma[1];
421: s->slave.event = omap_i2c_event;
422: s->slave.recv = omap_i2c_rx;
423: s->slave.send = omap_i2c_tx;
424: s->bus = i2c_init_bus();
425: omap_i2c_reset(s);
426:
427: iomemtype = cpu_register_io_memory(0, omap_i2c_readfn,
428: omap_i2c_writefn, s);
429: cpu_register_physical_memory(s->base, 0x800, iomemtype);
430:
431: return s;
432: }
433:
434: i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)
435: {
436: return s->bus;
437: }