29 |
29 |
i2c_slave slave;
|
30 |
30 |
i2c_bus *bus;
|
31 |
31 |
|
|
32 |
uint8_t revision;
|
32 |
33 |
uint8_t mask;
|
33 |
34 |
uint16_t stat;
|
34 |
35 |
uint16_t dma;
|
... | ... | |
44 |
45 |
uint16_t test;
|
45 |
46 |
};
|
46 |
47 |
|
|
48 |
#define OMAP2_INTR_REV 0x34
|
|
49 |
#define OMAP2_GC_REV 0x34
|
|
50 |
|
47 |
51 |
static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
|
48 |
52 |
{
|
49 |
53 |
qemu_set_irq(s->irq, s->stat & s->mask);
|
... | ... | |
124 |
128 |
i2c_end_transfer(s->bus);
|
125 |
129 |
s->control &= ~(1 << 1); /* STP */
|
126 |
130 |
s->count_cur = s->count;
|
|
131 |
s->txlen = 0;
|
127 |
132 |
} else if ((s->control >> 9) & 1) { /* TRX */
|
128 |
133 |
while (ack && s->txlen)
|
129 |
134 |
ack = (i2c_send(s->bus,
|
... | ... | |
162 |
167 |
i2c_end_transfer(s->bus);
|
163 |
168 |
s->control &= ~(1 << 1); /* STP */
|
164 |
169 |
s->count_cur = s->count;
|
|
170 |
s->txlen = 0;
|
165 |
171 |
} else {
|
166 |
172 |
s->stat |= 1 << 2; /* ARDY */
|
167 |
173 |
s->control &= ~(1 << 10); /* MST */
|
... | ... | |
201 |
207 |
|
202 |
208 |
switch (offset) {
|
203 |
209 |
case 0x00: /* I2C_REV */
|
204 |
|
/* TODO: set a value greater or equal to real hardware */
|
205 |
|
return 0x11; /* REV */
|
|
210 |
return s->revision; /* REV */
|
206 |
211 |
|
207 |
212 |
case 0x04: /* I2C_IE */
|
208 |
213 |
return s->mask;
|
... | ... | |
211 |
216 |
return s->stat | (i2c_bus_busy(s->bus) << 12);
|
212 |
217 |
|
213 |
218 |
case 0x0c: /* I2C_IV */
|
|
219 |
if (s->revision >= OMAP2_INTR_REV)
|
|
220 |
break;
|
214 |
221 |
ret = ffs(s->stat & s->mask);
|
215 |
222 |
if (ret)
|
216 |
223 |
s->stat ^= 1 << (ret - 1);
|
217 |
224 |
omap_i2c_interrupts_update(s);
|
218 |
225 |
return ret;
|
219 |
226 |
|
|
227 |
case 0x10: /* I2C_SYSS */
|
|
228 |
return (s->control >> 15) & 1; /* I2C_EN */
|
|
229 |
|
220 |
230 |
case 0x14: /* I2C_BUF */
|
221 |
231 |
return s->dma;
|
222 |
232 |
|
... | ... | |
242 |
252 |
} else
|
243 |
253 |
/* XXX: remote access (qualifier) error - what's that? */;
|
244 |
254 |
if (!s->rxlen) {
|
245 |
|
s->stat |= ~(1 << 3); /* RRDY */
|
|
255 |
s->stat &= ~(1 << 3); /* RRDY */
|
246 |
256 |
if (((s->control >> 10) & 1) && /* MST */
|
247 |
257 |
((~s->control >> 9) & 1)) { /* TRX */
|
248 |
258 |
s->stat |= 1 << 2; /* ARDY */
|
... | ... | |
254 |
264 |
omap_i2c_interrupts_update(s);
|
255 |
265 |
return ret;
|
256 |
266 |
|
|
267 |
case 0x20: /* I2C_SYSC */
|
|
268 |
return 0;
|
|
269 |
|
257 |
270 |
case 0x24: /* I2C_CON */
|
258 |
271 |
return s->control;
|
259 |
272 |
|
... | ... | |
293 |
306 |
|
294 |
307 |
switch (offset) {
|
295 |
308 |
case 0x00: /* I2C_REV */
|
296 |
|
case 0x08: /* I2C_STAT */
|
297 |
309 |
case 0x0c: /* I2C_IV */
|
298 |
|
OMAP_BAD_REG(addr);
|
|
310 |
case 0x10: /* I2C_SYSS */
|
|
311 |
OMAP_RO_REG(addr);
|
299 |
312 |
return;
|
300 |
313 |
|
301 |
314 |
case 0x04: /* I2C_IE */
|
302 |
|
s->mask = value & 0x1f;
|
|
315 |
s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
|
|
316 |
break;
|
|
317 |
|
|
318 |
case 0x08: /* I2C_STAT */
|
|
319 |
if (s->revision < OMAP2_INTR_REV) {
|
|
320 |
OMAP_RO_REG(addr);
|
|
321 |
return;
|
|
322 |
}
|
|
323 |
|
|
324 |
s->stat &= ~(value & 0x3f);
|
|
325 |
omap_i2c_interrupts_update(s);
|
303 |
326 |
break;
|
304 |
327 |
|
305 |
328 |
case 0x14: /* I2C_BUF */
|
... | ... | |
335 |
358 |
omap_i2c_interrupts_update(s);
|
336 |
359 |
break;
|
337 |
360 |
|
|
361 |
case 0x20: /* I2C_SYSC */
|
|
362 |
if (s->revision < OMAP2_INTR_REV) {
|
|
363 |
OMAP_BAD_REG(addr);
|
|
364 |
return;
|
|
365 |
}
|
|
366 |
|
|
367 |
if (value & 2)
|
|
368 |
omap_i2c_reset(s);
|
|
369 |
break;
|
|
370 |
|
338 |
371 |
case 0x24: /* I2C_CON */
|
339 |
|
s->control = value & 0xcf07;
|
|
372 |
s->control = value & 0xcf87;
|
340 |
373 |
if (~value & (1 << 15)) { /* I2C_EN */
|
341 |
|
omap_i2c_reset(s);
|
|
374 |
if (s->revision < OMAP2_INTR_REV)
|
|
375 |
omap_i2c_reset(s);
|
342 |
376 |
break;
|
343 |
377 |
}
|
344 |
|
if (~value & (1 << 10)) { /* MST */
|
|
378 |
if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
|
345 |
379 |
printf("%s: I^2C slave mode not supported\n", __FUNCTION__);
|
346 |
380 |
break;
|
347 |
381 |
}
|
348 |
|
if (value & (1 << 9)) { /* XA */
|
|
382 |
if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */
|
349 |
383 |
printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__);
|
350 |
384 |
break;
|
351 |
385 |
}
|
352 |
|
if (value & (1 << 0)) { /* STT */
|
|
386 |
if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */
|
353 |
387 |
nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */
|
354 |
388 |
(~value >> 9) & 1); /* TRX */
|
355 |
389 |
s->stat |= nack << 1; /* NACK */
|
356 |
390 |
s->control &= ~(1 << 0); /* STT */
|
357 |
391 |
if (nack)
|
358 |
392 |
s->control &= ~(1 << 1); /* STP */
|
359 |
|
else
|
|
393 |
else {
|
|
394 |
s->count_cur = s->count;
|
360 |
395 |
omap_i2c_fifo_run(s);
|
|
396 |
}
|
361 |
397 |
omap_i2c_interrupts_update(s);
|
362 |
398 |
}
|
363 |
399 |
break;
|
... | ... | |
384 |
420 |
break;
|
385 |
421 |
|
386 |
422 |
case 0x3c: /* I2C_SYSTEST */
|
387 |
|
s->test = value & 0xf00f;
|
|
423 |
s->test = value & 0xf80f;
|
|
424 |
if (value & (1 << 11)) /* SBB */
|
|
425 |
if (s->revision >= OMAP2_INTR_REV) {
|
|
426 |
s->stat |= 0x3f;
|
|
427 |
omap_i2c_interrupts_update(s);
|
|
428 |
}
|
388 |
429 |
if (value & (1 << 15)) /* ST_EN */
|
389 |
430 |
printf("%s: System Test not supported\n", __FUNCTION__);
|
390 |
431 |
break;
|
... | ... | |
395 |
436 |
}
|
396 |
437 |
}
|
397 |
438 |
|
|
439 |
static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr,
|
|
440 |
uint32_t value)
|
|
441 |
{
|
|
442 |
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
|
|
443 |
int offset = addr & OMAP_MPUI_REG_MASK;
|
|
444 |
|
|
445 |
switch (offset) {
|
|
446 |
case 0x1c: /* I2C_DATA */
|
|
447 |
if (s->txlen > 2) {
|
|
448 |
/* XXX: remote access (qualifier) error - what's that? */
|
|
449 |
break;
|
|
450 |
}
|
|
451 |
s->fifo <<= 8;
|
|
452 |
s->txlen += 1;
|
|
453 |
s->fifo |= value & 0xff;
|
|
454 |
s->stat &= ~(1 << 10); /* XUDF */
|
|
455 |
if (s->txlen > 2)
|
|
456 |
s->stat &= ~(1 << 4); /* XRDY */
|
|
457 |
omap_i2c_fifo_run(s);
|
|
458 |
omap_i2c_interrupts_update(s);
|
|
459 |
break;
|
|
460 |
|
|
461 |
default:
|
|
462 |
OMAP_BAD_REG(addr);
|
|
463 |
return;
|
|
464 |
}
|
|
465 |
}
|
|
466 |
|
398 |
467 |
static CPUReadMemoryFunc *omap_i2c_readfn[] = {
|
399 |
468 |
omap_badwidth_read16,
|
400 |
469 |
omap_i2c_read,
|
... | ... | |
402 |
471 |
};
|
403 |
472 |
|
404 |
473 |
static CPUWriteMemoryFunc *omap_i2c_writefn[] = {
|
405 |
|
omap_badwidth_write16,
|
|
474 |
omap_i2c_writeb, /* Only the last fifo write can be 8 bit. */
|
406 |
475 |
omap_i2c_write,
|
407 |
|
omap_i2c_write, /* TODO: Only the last fifo write can be 8 bit. */
|
|
476 |
omap_badwidth_write16,
|
408 |
477 |
};
|
409 |
478 |
|
410 |
479 |
struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
|
... | ... | |
414 |
483 |
struct omap_i2c_s *s = (struct omap_i2c_s *)
|
415 |
484 |
qemu_mallocz(sizeof(struct omap_i2c_s));
|
416 |
485 |
|
|
486 |
/* TODO: set a value greater or equal to real hardware */
|
|
487 |
s->revision = 0x11;
|
417 |
488 |
s->base = base;
|
418 |
489 |
s->irq = irq;
|
419 |
490 |
s->drq[0] = dma[0];
|
... | ... | |
431 |
502 |
return s;
|
432 |
503 |
}
|
433 |
504 |
|
|
505 |
struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
|
|
506 |
qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk)
|
|
507 |
{
|
|
508 |
int iomemtype;
|
|
509 |
struct omap_i2c_s *s = (struct omap_i2c_s *)
|
|
510 |
qemu_mallocz(sizeof(struct omap_i2c_s));
|
|
511 |
|
|
512 |
s->revision = 0x34;
|
|
513 |
s->irq = irq;
|
|
514 |
s->drq[0] = dma[0];
|
|
515 |
s->drq[1] = dma[1];
|
|
516 |
s->slave.event = omap_i2c_event;
|
|
517 |
s->slave.recv = omap_i2c_rx;
|
|
518 |
s->slave.send = omap_i2c_tx;
|
|
519 |
s->bus = i2c_init_bus();
|
|
520 |
omap_i2c_reset(s);
|
|
521 |
|
|
522 |
iomemtype = cpu_register_io_memory(0, omap_i2c_readfn,
|
|
523 |
omap_i2c_writefn, s);
|
|
524 |
s->base = omap_l4_attach(ta, 0, iomemtype);
|
|
525 |
|
|
526 |
return s;
|
|
527 |
}
|
|
528 |
|
434 |
529 |
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)
|
435 |
530 |
{
|
436 |
531 |
return s->bus;
|