Revision 02645926
b/Changelog | ||
---|---|---|
5 | 5 |
- CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau) |
6 | 6 |
- Several Sparc fixes (Aurelien Jarno, Blue Swirl, Robert Reif) |
7 | 7 |
- MIPS 64-bit FPU support (Thiemo Seufer) |
8 |
- Xscale PDA emulation (Andrzei Zaborowski)
|
|
8 |
- Xscale PDA emulation (Andrzej Zaborowski)
|
|
9 | 9 |
- ColdFire system emulation (Paul Brook) |
10 | 10 |
- Improved SH4 support (Magnus Damm) |
11 | 11 |
- MIPS64 support (Aurelien Jarno, Thiemo Seufer) |
... | ... | |
16 | 16 |
- SPARC32PLUS execution support (Blue Swirl) |
17 | 17 |
- MIPS mipssim pequdo machine (Thiemo Seufer) |
18 | 18 |
- Strace for Linux userland emulation (Stuart Anderson, Thayne Harbaugh) |
19 |
- OMAP310 MPU emulation plus Palm T|E machine (Andrzej Zaborowski) |
|
19 | 20 |
|
20 | 21 |
version 0.9.0: |
21 | 22 |
|
b/Makefile.target | ||
---|---|---|
519 | 519 |
VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o |
520 | 520 |
VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o |
521 | 521 |
VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o ecc.o $(AUDIODRV) wm8750.o |
522 |
VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o palm.o tsc210x.o |
|
522 |
VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o omap_i2c.o |
|
523 |
VL_OBJS+= palm.o tsc210x.o |
|
523 | 524 |
CPPFLAGS += -DHAS_AUDIO |
524 | 525 |
endif |
525 | 526 |
ifeq ($(TARGET_BASE_ARCH), sh4) |
b/hw/omap.c | ||
---|---|---|
24 | 24 |
/* Should signal the TCMI */ |
25 | 25 |
uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) |
26 | 26 |
{ |
27 |
uint8_t ret; |
|
28 |
|
|
27 | 29 |
OMAP_8B_REG(addr); |
28 |
return 0; |
|
30 |
cpu_physical_memory_read(addr, &ret, 1); |
|
31 |
return ret; |
|
29 | 32 |
} |
30 | 33 |
|
31 | 34 |
void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, |
... | ... | |
3466 | 3469 |
} |
3467 | 3470 |
|
3468 | 3471 |
static CPUReadMemoryFunc *omap_pwl_readfn[] = { |
3472 |
omap_pwl_read, |
|
3469 | 3473 |
omap_badwidth_read8, |
3470 | 3474 |
omap_badwidth_read8, |
3471 |
omap_pwl_read, |
|
3472 | 3475 |
}; |
3473 | 3476 |
|
3474 | 3477 |
static CPUWriteMemoryFunc *omap_pwl_writefn[] = { |
3478 |
omap_pwl_write, |
|
3475 | 3479 |
omap_badwidth_write8, |
3476 | 3480 |
omap_badwidth_write8, |
3477 |
omap_pwl_write, |
|
3478 | 3481 |
}; |
3479 | 3482 |
|
3480 | 3483 |
void omap_pwl_reset(struct omap_mpu_state_s *s) |
... | ... | |
3571 | 3574 |
} |
3572 | 3575 |
|
3573 | 3576 |
static CPUReadMemoryFunc *omap_pwt_readfn[] = { |
3577 |
omap_pwt_read, |
|
3574 | 3578 |
omap_badwidth_read8, |
3575 | 3579 |
omap_badwidth_read8, |
3576 |
omap_pwt_read, |
|
3577 | 3580 |
}; |
3578 | 3581 |
|
3579 | 3582 |
static CPUWriteMemoryFunc *omap_pwt_writefn[] = { |
3583 |
omap_pwt_write, |
|
3580 | 3584 |
omap_badwidth_write8, |
3581 | 3585 |
omap_badwidth_write8, |
3582 |
omap_pwt_write, |
|
3583 | 3586 |
}; |
3584 | 3587 |
|
3585 | 3588 |
void omap_pwt_reset(struct omap_mpu_state_s *s) |
... | ... | |
3603 | 3606 |
cpu_register_physical_memory(s->pwt.base, 0x800, iomemtype); |
3604 | 3607 |
} |
3605 | 3608 |
|
3606 |
/* Inter-Integrated Circuit Controller (only the "New I2C") */ |
|
3607 |
struct omap_i2c_s { |
|
3608 |
target_phys_addr_t base; |
|
3609 |
qemu_irq irq; |
|
3610 |
qemu_irq drq[2]; |
|
3611 |
i2c_slave slave; |
|
3612 |
i2c_bus *bus; |
|
3613 |
|
|
3614 |
uint8_t mask; |
|
3615 |
uint16_t stat; |
|
3616 |
uint16_t dma; |
|
3617 |
uint16_t count; |
|
3618 |
int count_cur; |
|
3619 |
uint32_t fifo; |
|
3620 |
int rxlen; |
|
3621 |
int txlen; |
|
3622 |
uint16_t control; |
|
3623 |
uint16_t addr[2]; |
|
3624 |
uint8_t divider; |
|
3625 |
uint8_t times[2]; |
|
3626 |
uint16_t test; |
|
3627 |
}; |
|
3628 |
|
|
3629 |
static void omap_i2c_interrupts_update(struct omap_i2c_s *s) |
|
3630 |
{ |
|
3631 |
qemu_set_irq(s->irq, s->stat & s->mask); |
|
3632 |
if ((s->dma >> 15) & 1) /* RDMA_EN */ |
|
3633 |
qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */ |
|
3634 |
if ((s->dma >> 7) & 1) /* XDMA_EN */ |
|
3635 |
qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */ |
|
3636 |
} |
|
3637 |
|
|
3638 |
/* These are only stubs now. */ |
|
3639 |
static void omap_i2c_event(i2c_slave *i2c, enum i2c_event event) |
|
3640 |
{ |
|
3641 |
struct omap_i2c_s *s = (struct omap_i2c_s *) i2c; |
|
3642 |
|
|
3643 |
if ((~s->control >> 15) & 1) /* I2C_EN */ |
|
3644 |
return; |
|
3645 |
|
|
3646 |
switch (event) { |
|
3647 |
case I2C_START_SEND: |
|
3648 |
case I2C_START_RECV: |
|
3649 |
s->stat |= 1 << 9; /* AAS */ |
|
3650 |
break; |
|
3651 |
case I2C_FINISH: |
|
3652 |
s->stat |= 1 << 2; /* ARDY */ |
|
3653 |
break; |
|
3654 |
case I2C_NACK: |
|
3655 |
s->stat |= 1 << 1; /* NACK */ |
|
3656 |
break; |
|
3657 |
} |
|
3658 |
|
|
3659 |
omap_i2c_interrupts_update(s); |
|
3660 |
} |
|
3661 |
|
|
3662 |
static int omap_i2c_rx(i2c_slave *i2c) |
|
3663 |
{ |
|
3664 |
struct omap_i2c_s *s = (struct omap_i2c_s *) i2c; |
|
3665 |
uint8_t ret = 0; |
|
3666 |
|
|
3667 |
if ((~s->control >> 15) & 1) /* I2C_EN */ |
|
3668 |
return -1; |
|
3669 |
|
|
3670 |
if (s->txlen) |
|
3671 |
ret = s->fifo >> ((-- s->txlen) << 3) & 0xff; |
|
3672 |
else |
|
3673 |
s->stat |= 1 << 10; /* XUDF */ |
|
3674 |
s->stat |= 1 << 4; /* XRDY */ |
|
3675 |
|
|
3676 |
omap_i2c_interrupts_update(s); |
|
3677 |
return ret; |
|
3678 |
} |
|
3679 |
|
|
3680 |
static int omap_i2c_tx(i2c_slave *i2c, uint8_t data) |
|
3681 |
{ |
|
3682 |
struct omap_i2c_s *s = (struct omap_i2c_s *) i2c; |
|
3683 |
|
|
3684 |
if ((~s->control >> 15) & 1) /* I2C_EN */ |
|
3685 |
return 1; |
|
3686 |
|
|
3687 |
if (s->rxlen < 4) |
|
3688 |
s->fifo |= data << ((s->rxlen ++) << 3); |
|
3689 |
else |
|
3690 |
s->stat |= 1 << 11; /* ROVR */ |
|
3691 |
s->stat |= 1 << 3; /* RRDY */ |
|
3692 |
|
|
3693 |
omap_i2c_interrupts_update(s); |
|
3694 |
return 1; |
|
3695 |
} |
|
3696 |
|
|
3697 |
static void omap_i2c_fifo_run(struct omap_i2c_s *s) |
|
3698 |
{ |
|
3699 |
int ack = 1; |
|
3700 |
|
|
3701 |
if (!i2c_bus_busy(s->bus)) |
|
3702 |
return; |
|
3703 |
|
|
3704 |
if ((s->control >> 2) & 1) { /* RM */ |
|
3705 |
if ((s->control >> 1) & 1) { /* STP */ |
|
3706 |
i2c_end_transfer(s->bus); |
|
3707 |
s->control &= ~(1 << 1); /* STP */ |
|
3708 |
s->count_cur = s->count; |
|
3709 |
} else if ((s->control >> 9) & 1) { /* TRX */ |
|
3710 |
while (ack && s->txlen) |
|
3711 |
ack = (i2c_send(s->bus, |
|
3712 |
(s->fifo >> ((-- s->txlen) << 3)) & |
|
3713 |
0xff) >= 0); |
|
3714 |
s->stat |= 1 << 4; /* XRDY */ |
|
3715 |
} else { |
|
3716 |
while (s->rxlen < 4) |
|
3717 |
s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3); |
|
3718 |
s->stat |= 1 << 3; /* RRDY */ |
|
3719 |
} |
|
3720 |
} else { |
|
3721 |
if ((s->control >> 9) & 1) { /* TRX */ |
|
3722 |
while (ack && s->count_cur && s->txlen) { |
|
3723 |
ack = (i2c_send(s->bus, |
|
3724 |
(s->fifo >> ((-- s->txlen) << 3)) & |
|
3725 |
0xff) >= 0); |
|
3726 |
s->count_cur --; |
|
3727 |
} |
|
3728 |
if (ack && s->count_cur) |
|
3729 |
s->stat |= 1 << 4; /* XRDY */ |
|
3730 |
if (!s->count_cur) { |
|
3731 |
s->stat |= 1 << 2; /* ARDY */ |
|
3732 |
s->control &= ~(1 << 10); /* MST */ |
|
3733 |
} |
|
3734 |
} else { |
|
3735 |
while (s->count_cur && s->rxlen < 4) { |
|
3736 |
s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3); |
|
3737 |
s->count_cur --; |
|
3738 |
} |
|
3739 |
if (s->rxlen) |
|
3740 |
s->stat |= 1 << 3; /* RRDY */ |
|
3741 |
} |
|
3742 |
if (!s->count_cur) { |
|
3743 |
if ((s->control >> 1) & 1) { /* STP */ |
|
3744 |
i2c_end_transfer(s->bus); |
|
3745 |
s->control &= ~(1 << 1); /* STP */ |
|
3746 |
s->count_cur = s->count; |
|
3747 |
} else { |
|
3748 |
s->stat |= 1 << 2; /* ARDY */ |
|
3749 |
s->control &= ~(1 << 10); /* MST */ |
|
3750 |
} |
|
3751 |
} |
|
3752 |
} |
|
3753 |
|
|
3754 |
s->stat |= (!ack) << 1; /* NACK */ |
|
3755 |
if (!ack) |
|
3756 |
s->control &= ~(1 << 1); /* STP */ |
|
3757 |
} |
|
3758 |
|
|
3759 |
static void omap_i2c_reset(struct omap_i2c_s *s) |
|
3760 |
{ |
|
3761 |
s->mask = 0; |
|
3762 |
s->stat = 0; |
|
3763 |
s->dma = 0; |
|
3764 |
s->count = 0; |
|
3765 |
s->count_cur = 0; |
|
3766 |
s->fifo = 0; |
|
3767 |
s->rxlen = 0; |
|
3768 |
s->txlen = 0; |
|
3769 |
s->control = 0; |
|
3770 |
s->addr[0] = 0; |
|
3771 |
s->addr[1] = 0; |
|
3772 |
s->divider = 0; |
|
3773 |
s->times[0] = 0; |
|
3774 |
s->times[1] = 0; |
|
3775 |
s->test = 0; |
|
3776 |
} |
|
3777 |
|
|
3778 |
static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr) |
|
3779 |
{ |
|
3780 |
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque; |
|
3781 |
int offset = addr - s->base; |
|
3782 |
uint16_t ret; |
|
3783 |
|
|
3784 |
switch (offset) { |
|
3785 |
case 0x00: /* I2C_REV */ |
|
3786 |
/* TODO: set a value greater or equal to real hardware */ |
|
3787 |
return 0x11; /* REV */ |
|
3788 |
|
|
3789 |
case 0x04: /* I2C_IE */ |
|
3790 |
return s->mask; |
|
3791 |
|
|
3792 |
case 0x08: /* I2C_STAT */ |
|
3793 |
return s->stat | (i2c_bus_busy(s->bus) << 12); |
|
3794 |
|
|
3795 |
case 0x0c: /* I2C_IV */ |
|
3796 |
ret = ffs(s->stat & s->mask); |
|
3797 |
if (ret) |
|
3798 |
s->stat ^= 1 << (ret - 1); |
|
3799 |
omap_i2c_interrupts_update(s); |
|
3800 |
return ret; |
|
3801 |
|
|
3802 |
case 0x14: /* I2C_BUF */ |
|
3803 |
return s->dma; |
|
3804 |
|
|
3805 |
case 0x18: /* I2C_CNT */ |
|
3806 |
return s->count_cur; /* DCOUNT */ |
|
3807 |
|
|
3808 |
case 0x1c: /* I2C_DATA */ |
|
3809 |
ret = 0; |
|
3810 |
if (s->control & (1 << 14)) { /* BE */ |
|
3811 |
ret |= ((s->fifo >> 0) & 0xff) << 8; |
|
3812 |
ret |= ((s->fifo >> 8) & 0xff) << 0; |
|
3813 |
} else { |
|
3814 |
ret |= ((s->fifo >> 8) & 0xff) << 8; |
|
3815 |
ret |= ((s->fifo >> 0) & 0xff) << 0; |
|
3816 |
} |
|
3817 |
if (s->rxlen == 1) { |
|
3818 |
s->stat |= 1 << 15; /* SBD */ |
|
3819 |
s->rxlen = 0; |
|
3820 |
} else if (s->rxlen > 1) { |
|
3821 |
if (s->rxlen > 2) |
|
3822 |
s->fifo >>= 16; |
|
3823 |
s->rxlen -= 2; |
|
3824 |
} else |
|
3825 |
/* XXX: remote access (qualifier) error - what's that? */; |
|
3826 |
if (!s->rxlen) { |
|
3827 |
s->stat |= ~(1 << 3); /* RRDY */ |
|
3828 |
if (((s->control >> 10) & 1) && /* MST */ |
|
3829 |
((~s->control >> 9) & 1)) { /* TRX */ |
|
3830 |
s->stat |= 1 << 2; /* ARDY */ |
|
3831 |
s->control &= ~(1 << 10); /* MST */ |
|
3832 |
} |
|
3833 |
} |
|
3834 |
s->stat &= ~(1 << 11); /* ROVR */ |
|
3835 |
omap_i2c_fifo_run(s); |
|
3836 |
omap_i2c_interrupts_update(s); |
|
3837 |
return ret; |
|
3838 |
|
|
3839 |
case 0x24: /* I2C_CON */ |
|
3840 |
return s->control; |
|
3841 |
|
|
3842 |
case 0x28: /* I2C_OA */ |
|
3843 |
return s->addr[0]; |
|
3844 |
|
|
3845 |
case 0x2c: /* I2C_SA */ |
|
3846 |
return s->addr[1]; |
|
3847 |
|
|
3848 |
case 0x30: /* I2C_PSC */ |
|
3849 |
return s->divider; |
|
3850 |
|
|
3851 |
case 0x34: /* I2C_SCLL */ |
|
3852 |
return s->times[0]; |
|
3853 |
|
|
3854 |
case 0x38: /* I2C_SCLH */ |
|
3855 |
return s->times[1]; |
|
3856 |
|
|
3857 |
case 0x3c: /* I2C_SYSTEST */ |
|
3858 |
if (s->test & (1 << 15)) { /* ST_EN */ |
|
3859 |
s->test ^= 0xa; |
|
3860 |
return s->test; |
|
3861 |
} else |
|
3862 |
return s->test & ~0x300f; |
|
3863 |
} |
|
3864 |
|
|
3865 |
OMAP_BAD_REG(addr); |
|
3866 |
return 0; |
|
3867 |
} |
|
3868 |
|
|
3869 |
static void omap_i2c_write(void *opaque, target_phys_addr_t addr, |
|
3870 |
uint32_t value) |
|
3871 |
{ |
|
3872 |
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque; |
|
3873 |
int offset = addr - s->base; |
|
3874 |
int nack; |
|
3875 |
|
|
3876 |
switch (offset) { |
|
3877 |
case 0x00: /* I2C_REV */ |
|
3878 |
case 0x08: /* I2C_STAT */ |
|
3879 |
case 0x0c: /* I2C_IV */ |
|
3880 |
OMAP_BAD_REG(addr); |
|
3881 |
return; |
|
3882 |
|
|
3883 |
case 0x04: /* I2C_IE */ |
|
3884 |
s->mask = value & 0x1f; |
|
3885 |
break; |
|
3886 |
|
|
3887 |
case 0x14: /* I2C_BUF */ |
|
3888 |
s->dma = value & 0x8080; |
|
3889 |
if (value & (1 << 15)) /* RDMA_EN */ |
|
3890 |
s->mask &= ~(1 << 3); /* RRDY_IE */ |
|
3891 |
if (value & (1 << 7)) /* XDMA_EN */ |
|
3892 |
s->mask &= ~(1 << 4); /* XRDY_IE */ |
|
3893 |
break; |
|
3894 |
|
|
3895 |
case 0x18: /* I2C_CNT */ |
|
3896 |
s->count = value; /* DCOUNT */ |
|
3897 |
break; |
|
3898 |
|
|
3899 |
case 0x1c: /* I2C_DATA */ |
|
3900 |
if (s->txlen > 2) { |
|
3901 |
/* XXX: remote access (qualifier) error - what's that? */ |
|
3902 |
break; |
|
3903 |
} |
|
3904 |
s->fifo <<= 16; |
|
3905 |
s->txlen += 2; |
|
3906 |
if (s->control & (1 << 14)) { /* BE */ |
|
3907 |
s->fifo |= ((value >> 8) & 0xff) << 8; |
|
3908 |
s->fifo |= ((value >> 0) & 0xff) << 0; |
|
3909 |
} else { |
|
3910 |
s->fifo |= ((value >> 0) & 0xff) << 8; |
|
3911 |
s->fifo |= ((value >> 8) & 0xff) << 0; |
|
3912 |
} |
|
3913 |
s->stat &= ~(1 << 10); /* XUDF */ |
|
3914 |
if (s->txlen > 2) |
|
3915 |
s->stat &= ~(1 << 4); /* XRDY */ |
|
3916 |
omap_i2c_fifo_run(s); |
|
3917 |
omap_i2c_interrupts_update(s); |
|
3918 |
break; |
|
3919 |
|
|
3920 |
case 0x24: /* I2C_CON */ |
|
3921 |
s->control = value & 0xcf07; |
|
3922 |
if (~value & (1 << 15)) { /* I2C_EN */ |
|
3923 |
omap_i2c_reset(s); |
|
3924 |
break; |
|
3925 |
} |
|
3926 |
if (~value & (1 << 10)) { /* MST */ |
|
3927 |
printf("%s: I^2C slave mode not supported\n", __FUNCTION__); |
|
3928 |
break; |
|
3929 |
} |
|
3930 |
if (value & (1 << 9)) { /* XA */ |
|
3931 |
printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__); |
|
3932 |
break; |
|
3933 |
} |
|
3934 |
if (value & (1 << 0)) { /* STT */ |
|
3935 |
nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */ |
|
3936 |
(~value >> 9) & 1); /* TRX */ |
|
3937 |
s->stat |= nack << 1; /* NACK */ |
|
3938 |
s->control &= ~(1 << 0); /* STT */ |
|
3939 |
if (nack) |
|
3940 |
s->control &= ~(1 << 1); /* STP */ |
|
3941 |
else |
|
3942 |
omap_i2c_fifo_run(s); |
|
3943 |
omap_i2c_interrupts_update(s); |
|
3944 |
} |
|
3945 |
break; |
|
3946 |
|
|
3947 |
case 0x28: /* I2C_OA */ |
|
3948 |
s->addr[0] = value & 0x3ff; |
|
3949 |
i2c_set_slave_address(&s->slave, value & 0x7f); |
|
3950 |
break; |
|
3951 |
|
|
3952 |
case 0x2c: /* I2C_SA */ |
|
3953 |
s->addr[1] = value & 0x3ff; |
|
3954 |
break; |
|
3955 |
|
|
3956 |
case 0x30: /* I2C_PSC */ |
|
3957 |
s->divider = value; |
|
3958 |
break; |
|
3959 |
|
|
3960 |
case 0x34: /* I2C_SCLL */ |
|
3961 |
s->times[0] = value; |
|
3962 |
break; |
|
3963 |
|
|
3964 |
case 0x38: /* I2C_SCLH */ |
|
3965 |
s->times[1] = value; |
|
3966 |
break; |
|
3967 |
|
|
3968 |
case 0x3c: /* I2C_SYSTEST */ |
|
3969 |
s->test = value & 0xf00f; |
|
3970 |
if (value & (1 << 15)) /* ST_EN */ |
|
3971 |
printf("%s: System Test not supported\n", __FUNCTION__); |
|
3972 |
break; |
|
3973 |
|
|
3974 |
default: |
|
3975 |
OMAP_BAD_REG(addr); |
|
3976 |
return; |
|
3977 |
} |
|
3978 |
} |
|
3979 |
|
|
3980 |
static CPUReadMemoryFunc *omap_i2c_readfn[] = { |
|
3981 |
omap_badwidth_read16, |
|
3982 |
omap_i2c_read, |
|
3983 |
omap_badwidth_read16, |
|
3984 |
}; |
|
3985 |
|
|
3986 |
static CPUWriteMemoryFunc *omap_i2c_writefn[] = { |
|
3987 |
omap_badwidth_write16, |
|
3988 |
omap_i2c_write, |
|
3989 |
omap_i2c_write, /* TODO: Only the last fifo write can be 8 bit. */ |
|
3990 |
}; |
|
3991 |
|
|
3992 |
struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base, |
|
3993 |
qemu_irq irq, qemu_irq *dma, omap_clk clk) |
|
3994 |
{ |
|
3995 |
int iomemtype; |
|
3996 |
struct omap_i2c_s *s = (struct omap_i2c_s *) |
|
3997 |
qemu_mallocz(sizeof(struct omap_i2c_s)); |
|
3998 |
|
|
3999 |
s->base = base; |
|
4000 |
s->irq = irq; |
|
4001 |
s->drq[0] = dma[0]; |
|
4002 |
s->drq[1] = dma[1]; |
|
4003 |
s->slave.event = omap_i2c_event; |
|
4004 |
s->slave.recv = omap_i2c_rx; |
|
4005 |
s->slave.send = omap_i2c_tx; |
|
4006 |
s->bus = i2c_init_bus(); |
|
4007 |
omap_i2c_reset(s); |
|
4008 |
|
|
4009 |
iomemtype = cpu_register_io_memory(0, omap_i2c_readfn, |
|
4010 |
omap_i2c_writefn, s); |
|
4011 |
cpu_register_physical_memory(s->base, 0x800, iomemtype); |
|
4012 |
|
|
4013 |
return s; |
|
4014 |
} |
|
4015 |
|
|
4016 |
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s) |
|
4017 |
{ |
|
4018 |
return s->bus; |
|
4019 |
} |
|
4020 |
|
|
4021 | 3609 |
/* Real-time Clock module */ |
4022 | 3610 |
struct omap_rtc_s { |
4023 | 3611 |
target_phys_addr_t base; |
... | ... | |
4607 | 4195 |
|
4608 | 4196 |
s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER], |
4609 | 4197 |
omap_findclk(s, "clk32-kHz")); |
4198 |
|
|
4199 |
/* Register mappings not currenlty implemented: |
|
4200 |
* McBSP2 Comm fffb1000 - fffb17ff |
|
4201 |
* McBSP1 Audio fffb1800 - fffb1fff (not mapped on OMAP310) |
|
4202 |
* MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310) |
|
4203 |
* MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310) |
|
4204 |
* USB W2FC fffb4000 - fffb47ff |
|
4205 |
* Camera Interface fffb6800 - fffb6fff |
|
4206 |
* McBSP3 fffb7000 - fffb77ff (not mapped on OMAP310) |
|
4207 |
* USB Host fffba000 - fffba7ff |
|
4208 |
* FAC fffba800 - fffbafff |
|
4209 |
* HDQ/1-Wire fffbc000 - fffbc7ff |
|
4210 |
* LED1 fffbd000 - fffbd7ff |
|
4211 |
* LED2 fffbd800 - fffbdfff |
|
4212 |
* Mailbox fffcf000 - fffcf7ff |
|
4213 |
* Local bus IF fffec100 - fffec1ff |
|
4214 |
* Local bus MMU fffec200 - fffec2ff |
|
4215 |
* DSP MMU fffed200 - fffed2ff |
|
4216 |
*/ |
|
4217 |
|
|
4610 | 4218 |
qemu_register_reset(omap_mpu_reset, s); |
4611 | 4219 |
|
4612 | 4220 |
return s; |
b/hw/omap.h | ||
---|---|---|
475 | 475 |
void omap_uwire_attach(struct omap_uwire_s *s, |
476 | 476 |
struct uwire_slave_s *slave, int chipselect); |
477 | 477 |
|
478 |
struct omap_i2c_s; |
|
479 |
struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base, |
|
480 |
qemu_irq irq, qemu_irq *dma, omap_clk clk); |
|
481 |
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s); |
|
482 |
|
|
483 | 478 |
struct omap_rtc_s; |
484 | 479 |
struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base, |
485 | 480 |
qemu_irq *irq, omap_clk clk); |
... | ... | |
498 | 493 |
void omap_mmc_reset(struct omap_mmc_s *s); |
499 | 494 |
void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover); |
500 | 495 |
|
496 |
/* omap_i2c.c */ |
|
497 |
struct omap_i2c_s; |
|
498 |
struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base, |
|
499 |
qemu_irq irq, qemu_irq *dma, omap_clk clk); |
|
500 |
void omap_i2c_reset(struct omap_i2c_s *s); |
|
501 |
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s); |
|
502 |
|
|
501 | 503 |
# define cpu_is_omap310(cpu) (cpu->mpu_model == omap310) |
502 | 504 |
# define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510) |
503 | 505 |
# define cpu_is_omap15xx(cpu) \ |
... | ... | |
561 | 563 |
|
562 | 564 |
struct omap_i2c_s *i2c; |
563 | 565 |
|
566 |
struct omap_rtc_s *rtc; |
|
567 |
|
|
564 | 568 |
/* MPU private TIPB peripherals */ |
565 | 569 |
struct omap_intr_handler_s *ih[2]; |
566 | 570 |
|
b/hw/omap_i2c.c | ||
---|---|---|
1 |
/* |
|
2 |
* TI OMAP on-chip I2C controller. Only "new I2C" mode supported. |
|
3 |
* |
|
4 |
* Copyright (C) 2007 Andrzej Zaborowski <balrog@zabor.org> |
|
5 |
* |
|
6 |
* This program is free software; you can redistribute it and/or |
|
7 |
* modify it under the terms of the GNU General Public License as |
|
8 |
* published by the Free Software Foundation; either version 2 of |
|
9 |
* the License, or (at your option) any later version. |
|
10 |
* |
|
11 |
* This program is distributed in the hope that it will be useful, |
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
* GNU General Public License for more details. |
|
15 |
* |
|
16 |
* You should have received a copy of the GNU General Public License |
|
17 |
* along with this program; if not, write to the Free Software |
|
18 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
|
19 |
* MA 02111-1307 USA |
|
20 |
*/ |
|
21 |
#include "vl.h" |
|
22 |
|
|
23 |
struct omap_i2c_s { |
|
24 |
target_phys_addr_t base; |
|
25 |
qemu_irq irq; |
|
26 |
qemu_irq drq[2]; |
|
27 |
i2c_slave slave; |
|
28 |
i2c_bus *bus; |
|
29 |
|
|
30 |
uint8_t mask; |
|
31 |
uint16_t stat; |
|
32 |
uint16_t dma; |
|
33 |
uint16_t count; |
|
34 |
int count_cur; |
|
35 |
uint32_t fifo; |
|
36 |
int rxlen; |
|
37 |
int txlen; |
|
38 |
uint16_t control; |
|
39 |
uint16_t addr[2]; |
|
40 |
uint8_t divider; |
|
41 |
uint8_t times[2]; |
|
42 |
uint16_t test; |
|
43 |
}; |
|
44 |
|
|
45 |
static void omap_i2c_interrupts_update(struct omap_i2c_s *s) |
|
46 |
{ |
|
47 |
qemu_set_irq(s->irq, s->stat & s->mask); |
|
48 |
if ((s->dma >> 15) & 1) /* RDMA_EN */ |
|
49 |
qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */ |
|
50 |
if ((s->dma >> 7) & 1) /* XDMA_EN */ |
|
51 |
qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */ |
|
52 |
} |
|
53 |
|
|
54 |
/* These are only stubs now. */ |
|
55 |
static void omap_i2c_event(i2c_slave *i2c, enum i2c_event event) |
|
56 |
{ |
|
57 |
struct omap_i2c_s *s = (struct omap_i2c_s *) i2c; |
|
58 |
|
|
59 |
if ((~s->control >> 15) & 1) /* I2C_EN */ |
|
60 |
return; |
|
61 |
|
|
62 |
switch (event) { |
|
63 |
case I2C_START_SEND: |
|
64 |
case I2C_START_RECV: |
|
65 |
s->stat |= 1 << 9; /* AAS */ |
|
66 |
break; |
|
67 |
case I2C_FINISH: |
|
68 |
s->stat |= 1 << 2; /* ARDY */ |
|
69 |
break; |
|
70 |
case I2C_NACK: |
|
71 |
s->stat |= 1 << 1; /* NACK */ |
|
72 |
break; |
|
73 |
} |
|
74 |
|
|
75 |
omap_i2c_interrupts_update(s); |
|
76 |
} |
|
77 |
|
|
78 |
static int omap_i2c_rx(i2c_slave *i2c) |
|
79 |
{ |
|
80 |
struct omap_i2c_s *s = (struct omap_i2c_s *) i2c; |
|
81 |
uint8_t ret = 0; |
|
82 |
|
|
83 |
if ((~s->control >> 15) & 1) /* I2C_EN */ |
|
84 |
return -1; |
|
85 |
|
|
86 |
if (s->txlen) |
|
87 |
ret = s->fifo >> ((-- s->txlen) << 3) & 0xff; |
|
88 |
else |
|
89 |
s->stat |= 1 << 10; /* XUDF */ |
|
90 |
s->stat |= 1 << 4; /* XRDY */ |
|
91 |
|
|
92 |
omap_i2c_interrupts_update(s); |
|
93 |
return ret; |
|
94 |
} |
|
95 |
|
|
96 |
static int omap_i2c_tx(i2c_slave *i2c, uint8_t data) |
|
97 |
{ |
|
98 |
struct omap_i2c_s *s = (struct omap_i2c_s *) i2c; |
|
99 |
|
|
100 |
if ((~s->control >> 15) & 1) /* I2C_EN */ |
|
101 |
return 1; |
|
102 |
|
|
103 |
if (s->rxlen < 4) |
|
104 |
s->fifo |= data << ((s->rxlen ++) << 3); |
|
105 |
else |
|
106 |
s->stat |= 1 << 11; /* ROVR */ |
|
107 |
s->stat |= 1 << 3; /* RRDY */ |
|
108 |
|
|
109 |
omap_i2c_interrupts_update(s); |
|
110 |
return 1; |
|
111 |
} |
|
112 |
|
|
113 |
static void omap_i2c_fifo_run(struct omap_i2c_s *s) |
|
114 |
{ |
|
115 |
int ack = 1; |
|
116 |
|
|
117 |
if (!i2c_bus_busy(s->bus)) |
|
118 |
return; |
|
119 |
|
|
120 |
if ((s->control >> 2) & 1) { /* RM */ |
|
121 |
if ((s->control >> 1) & 1) { /* STP */ |
|
122 |
i2c_end_transfer(s->bus); |
|
123 |
s->control &= ~(1 << 1); /* STP */ |
|
124 |
s->count_cur = s->count; |
|
125 |
} else if ((s->control >> 9) & 1) { /* TRX */ |
|
126 |
while (ack && s->txlen) |
|
127 |
ack = (i2c_send(s->bus, |
|
128 |
(s->fifo >> ((-- s->txlen) << 3)) & |
|
129 |
0xff) >= 0); |
|
130 |
s->stat |= 1 << 4; /* XRDY */ |
|
131 |
} else { |
|
132 |
while (s->rxlen < 4) |
|
133 |
s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3); |
|
134 |
s->stat |= 1 << 3; /* RRDY */ |
|
135 |
} |
|
136 |
} else { |
|
137 |
if ((s->control >> 9) & 1) { /* TRX */ |
|
138 |
while (ack && s->count_cur && s->txlen) { |
|
139 |
ack = (i2c_send(s->bus, |
|
140 |
(s->fifo >> ((-- s->txlen) << 3)) & |
|
141 |
0xff) >= 0); |
|
142 |
s->count_cur --; |
|
143 |
} |
|
144 |
if (ack && s->count_cur) |
|
145 |
s->stat |= 1 << 4; /* XRDY */ |
|
146 |
if (!s->count_cur) { |
|
147 |
s->stat |= 1 << 2; /* ARDY */ |
|
148 |
s->control &= ~(1 << 10); /* MST */ |
|
149 |
} |
|
150 |
} else { |
|
151 |
while (s->count_cur && s->rxlen < 4) { |
|
152 |
s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3); |
|
153 |
s->count_cur --; |
|
154 |
} |
|
155 |
if (s->rxlen) |
|
156 |
s->stat |= 1 << 3; /* RRDY */ |
|
157 |
} |
|
158 |
if (!s->count_cur) { |
|
159 |
if ((s->control >> 1) & 1) { /* STP */ |
|
160 |
i2c_end_transfer(s->bus); |
|
161 |
s->control &= ~(1 << 1); /* STP */ |
|
162 |
s->count_cur = s->count; |
|
163 |
} else { |
|
164 |
s->stat |= 1 << 2; /* ARDY */ |
|
165 |
s->control &= ~(1 << 10); /* MST */ |
|
166 |
} |
|
167 |
} |
|
168 |
} |
|
169 |
|
|
170 |
s->stat |= (!ack) << 1; /* NACK */ |
|
171 |
if (!ack) |
|
172 |
s->control &= ~(1 << 1); /* STP */ |
|
173 |
} |
|
174 |
|
|
175 |
void omap_i2c_reset(struct omap_i2c_s *s) |
|
176 |
{ |
|
177 |
s->mask = 0; |
|
178 |
s->stat = 0; |
|
179 |
s->dma = 0; |
|
180 |
s->count = 0; |
|
181 |
s->count_cur = 0; |
|
182 |
s->fifo = 0; |
|
183 |
s->rxlen = 0; |
|
184 |
s->txlen = 0; |
|
185 |
s->control = 0; |
|
186 |
s->addr[0] = 0; |
|
187 |
s->addr[1] = 0; |
|
188 |
s->divider = 0; |
|
189 |
s->times[0] = 0; |
|
190 |
s->times[1] = 0; |
|
191 |
s->test = 0; |
|
192 |
} |
|
193 |
|
|
194 |
static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr) |
|
195 |
{ |
|
196 |
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque; |
|
197 |
int offset = addr - s->base; |
|
198 |
uint16_t ret; |
|
199 |
|
|
200 |
switch (offset) { |
|
201 |
case 0x00: /* I2C_REV */ |
|
202 |
/* TODO: set a value greater or equal to real hardware */ |
|
203 |
return 0x11; /* REV */ |
|
204 |
|
|
205 |
case 0x04: /* I2C_IE */ |
|
206 |
return s->mask; |
|
207 |
|
|
208 |
case 0x08: /* I2C_STAT */ |
|
209 |
return s->stat | (i2c_bus_busy(s->bus) << 12); |
|
210 |
|
|
211 |
case 0x0c: /* I2C_IV */ |
|
212 |
ret = ffs(s->stat & s->mask); |
|
213 |
if (ret) |
|
214 |
s->stat ^= 1 << (ret - 1); |
|
215 |
omap_i2c_interrupts_update(s); |
|
216 |
return ret; |
|
217 |
|
|
218 |
case 0x14: /* I2C_BUF */ |
|
219 |
return s->dma; |
|
220 |
|
|
221 |
case 0x18: /* I2C_CNT */ |
|
222 |
return s->count_cur; /* DCOUNT */ |
|
223 |
|
|
224 |
case 0x1c: /* I2C_DATA */ |
|
225 |
ret = 0; |
|
226 |
if (s->control & (1 << 14)) { /* BE */ |
|
227 |
ret |= ((s->fifo >> 0) & 0xff) << 8; |
|
228 |
ret |= ((s->fifo >> 8) & 0xff) << 0; |
|
229 |
} else { |
|
230 |
ret |= ((s->fifo >> 8) & 0xff) << 8; |
|
231 |
ret |= ((s->fifo >> 0) & 0xff) << 0; |
|
232 |
} |
|
233 |
if (s->rxlen == 1) { |
|
234 |
s->stat |= 1 << 15; /* SBD */ |
|
235 |
s->rxlen = 0; |
|
236 |
} else if (s->rxlen > 1) { |
|
237 |
if (s->rxlen > 2) |
|
238 |
s->fifo >>= 16; |
|
239 |
s->rxlen -= 2; |
|
240 |
} else |
|
241 |
/* XXX: remote access (qualifier) error - what's that? */; |
|
242 |
if (!s->rxlen) { |
|
243 |
s->stat |= ~(1 << 3); /* RRDY */ |
|
244 |
if (((s->control >> 10) & 1) && /* MST */ |
|
245 |
((~s->control >> 9) & 1)) { /* TRX */ |
|
246 |
s->stat |= 1 << 2; /* ARDY */ |
|
247 |
s->control &= ~(1 << 10); /* MST */ |
|
248 |
} |
|
249 |
} |
|
250 |
s->stat &= ~(1 << 11); /* ROVR */ |
|
251 |
omap_i2c_fifo_run(s); |
|
252 |
omap_i2c_interrupts_update(s); |
|
253 |
return ret; |
|
254 |
|
|
255 |
case 0x24: /* I2C_CON */ |
|
256 |
return s->control; |
|
257 |
|
|
258 |
case 0x28: /* I2C_OA */ |
|
259 |
return s->addr[0]; |
|
260 |
|
|
261 |
case 0x2c: /* I2C_SA */ |
|
262 |
return s->addr[1]; |
|
263 |
|
|
264 |
case 0x30: /* I2C_PSC */ |
|
265 |
return s->divider; |
|
266 |
|
|
267 |
case 0x34: /* I2C_SCLL */ |
|
268 |
return s->times[0]; |
|
269 |
|
|
270 |
case 0x38: /* I2C_SCLH */ |
|
271 |
return s->times[1]; |
|
272 |
|
|
273 |
case 0x3c: /* I2C_SYSTEST */ |
|
274 |
if (s->test & (1 << 15)) { /* ST_EN */ |
|
275 |
s->test ^= 0xa; |
|
276 |
return s->test; |
|
277 |
} else |
|
278 |
return s->test & ~0x300f; |
|
279 |
} |
|
280 |
|
|
281 |
OMAP_BAD_REG(addr); |
|
282 |
return 0; |
|
283 |
} |
|
284 |
|
|
285 |
static void omap_i2c_write(void *opaque, target_phys_addr_t addr, |
|
286 |
uint32_t value) |
|
287 |
{ |
|
288 |
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque; |
|
289 |
int offset = addr - s->base; |
|
290 |
int nack; |
|
291 |
|
|
292 |
switch (offset) { |
|
293 |
case 0x00: /* I2C_REV */ |
|
294 |
case 0x08: /* I2C_STAT */ |
|
295 |
case 0x0c: /* I2C_IV */ |
|
296 |
OMAP_BAD_REG(addr); |
|
297 |
return; |
|
298 |
|
|
299 |
case 0x04: /* I2C_IE */ |
|
300 |
s->mask = value & 0x1f; |
|
301 |
break; |
|
302 |
|
|
303 |
case 0x14: /* I2C_BUF */ |
|
304 |
s->dma = value & 0x8080; |
|
305 |
if (value & (1 << 15)) /* RDMA_EN */ |
|
306 |
s->mask &= ~(1 << 3); /* RRDY_IE */ |
|
307 |
if (value & (1 << 7)) /* XDMA_EN */ |
|
308 |
s->mask &= ~(1 << 4); /* XRDY_IE */ |
|
309 |
break; |
|
310 |
|
|
311 |
case 0x18: /* I2C_CNT */ |
|
312 |
s->count = value; /* DCOUNT */ |
|
313 |
break; |
|
314 |
|
|
315 |
case 0x1c: /* I2C_DATA */ |
|
316 |
if (s->txlen > 2) { |
|
317 |
/* XXX: remote access (qualifier) error - what's that? */ |
|
318 |
break; |
|
319 |
} |
|
320 |
s->fifo <<= 16; |
|
321 |
s->txlen += 2; |
|
322 |
if (s->control & (1 << 14)) { /* BE */ |
|
323 |
s->fifo |= ((value >> 8) & 0xff) << 8; |
|
324 |
s->fifo |= ((value >> 0) & 0xff) << 0; |
|
325 |
} else { |
|
326 |
s->fifo |= ((value >> 0) & 0xff) << 8; |
|
327 |
s->fifo |= ((value >> 8) & 0xff) << 0; |
|
328 |
} |
|
329 |
s->stat &= ~(1 << 10); /* XUDF */ |
|
330 |
if (s->txlen > 2) |
|
331 |
s->stat &= ~(1 << 4); /* XRDY */ |
|
332 |
omap_i2c_fifo_run(s); |
|
333 |
omap_i2c_interrupts_update(s); |
|
334 |
break; |
|
335 |
|
|
336 |
case 0x24: /* I2C_CON */ |
|
337 |
s->control = value & 0xcf07; |
|
338 |
if (~value & (1 << 15)) { /* I2C_EN */ |
|
339 |
omap_i2c_reset(s); |
|
340 |
break; |
|
341 |
} |
|
342 |
if (~value & (1 << 10)) { /* MST */ |
|
343 |
printf("%s: I^2C slave mode not supported\n", __FUNCTION__); |
|
344 |
break; |
|
345 |
} |
|
346 |
if (value & (1 << 9)) { /* XA */ |
|
347 |
printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__); |
|
348 |
break; |
|
349 |
} |
|
350 |
if (value & (1 << 0)) { /* STT */ |
|
351 |
nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */ |
|
352 |
(~value >> 9) & 1); /* TRX */ |
|
353 |
s->stat |= nack << 1; /* NACK */ |
|
354 |
s->control &= ~(1 << 0); /* STT */ |
|
355 |
if (nack) |
|
356 |
s->control &= ~(1 << 1); /* STP */ |
|
357 |
else |
|
358 |
omap_i2c_fifo_run(s); |
|
359 |
omap_i2c_interrupts_update(s); |
|
360 |
} |
|
361 |
break; |
|
362 |
|
|
363 |
case 0x28: /* I2C_OA */ |
|
364 |
s->addr[0] = value & 0x3ff; |
|
365 |
i2c_set_slave_address(&s->slave, value & 0x7f); |
|
366 |
break; |
|
367 |
|
|
368 |
case 0x2c: /* I2C_SA */ |
|
369 |
s->addr[1] = value & 0x3ff; |
|
370 |
break; |
|
371 |
|
|
372 |
case 0x30: /* I2C_PSC */ |
|
373 |
s->divider = value; |
|
374 |
break; |
|
375 |
|
|
376 |
case 0x34: /* I2C_SCLL */ |
|
377 |
s->times[0] = value; |
|
378 |
break; |
|
379 |
|
|
380 |
case 0x38: /* I2C_SCLH */ |
|
381 |
s->times[1] = value; |
|
382 |
break; |
|
383 |
|
|
384 |
case 0x3c: /* I2C_SYSTEST */ |
|
385 |
s->test = value & 0xf00f; |
|
386 |
if (value & (1 << 15)) /* ST_EN */ |
|
387 |
printf("%s: System Test not supported\n", __FUNCTION__); |
|
388 |
break; |
|
389 |
|
|
390 |
default: |
|
391 |
OMAP_BAD_REG(addr); |
|
392 |
return; |
|
393 |
} |
|
394 |
} |
|
395 |
|
|
396 |
static CPUReadMemoryFunc *omap_i2c_readfn[] = { |
|
397 |
omap_badwidth_read16, |
|
398 |
omap_i2c_read, |
|
399 |
omap_badwidth_read16, |
|
400 |
}; |
|
401 |
|
|
402 |
static CPUWriteMemoryFunc *omap_i2c_writefn[] = { |
|
403 |
omap_badwidth_write16, |
|
404 |
omap_i2c_write, |
|
405 |
omap_i2c_write, /* TODO: Only the last fifo write can be 8 bit. */ |
|
406 |
}; |
|
407 |
|
|
408 |
struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base, |
|
409 |
qemu_irq irq, qemu_irq *dma, omap_clk clk) |
|
410 |
{ |
|
411 |
int iomemtype; |
|
412 |
struct omap_i2c_s *s = (struct omap_i2c_s *) |
|
413 |
qemu_mallocz(sizeof(struct omap_i2c_s)); |
|
414 |
|
|
415 |
s->base = base; |
|
416 |
s->irq = irq; |
|
417 |
s->drq[0] = dma[0]; |
|
418 |
s->drq[1] = dma[1]; |
|
419 |
s->slave.event = omap_i2c_event; |
|
420 |
s->slave.recv = omap_i2c_rx; |
|
421 |
s->slave.send = omap_i2c_tx; |
|
422 |
s->bus = i2c_init_bus(); |
|
423 |
omap_i2c_reset(s); |
|
424 |
|
|
425 |
iomemtype = cpu_register_io_memory(0, omap_i2c_readfn, |
|
426 |
omap_i2c_writefn, s); |
|
427 |
cpu_register_physical_memory(s->base, 0x800, iomemtype); |
|
428 |
|
|
429 |
return s; |
|
430 |
} |
|
431 |
|
|
432 |
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s) |
|
433 |
{ |
|
434 |
return s->bus; |
|
435 |
} |
b/qemu-doc.texi | ||
---|---|---|
83 | 83 |
@item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor) |
84 | 84 |
@item Freescale MCF5208EVB (ColdFire V2). |
85 | 85 |
@item Arnewsh MCF5206 evaluation board (ColdFire V2). |
86 |
@item Palm Tungsten|E PDA (OMAP310 processor) |
|
86 | 87 |
@end itemize |
87 | 88 |
|
88 | 89 |
For user emulation, x86, PowerPC, ARM, MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported. |
... | ... | |
2208 | 2209 |
WM8750 audio CODEC on I@math{^2}C and I@math{^2}S busses |
2209 | 2210 |
@end itemize |
2210 | 2211 |
|
2212 |
The Palm Tungsten|E PDA (codename "Cheetah") emulation includes the |
|
2213 |
following elements: |
|
2214 |
|
|
2215 |
@itemize @minus |
|
2216 |
@item |
|
2217 |
Texas Instruments OMAP310 System-on-chip (ARM 925T core) |
|
2218 |
@item |
|
2219 |
ROM and RAM memories (ROM firmware image can be loaded with -option-rom) |
|
2220 |
@item |
|
2221 |
On-chip LCD controller |
|
2222 |
@item |
|
2223 |
On-chip Real Time Clock |
|
2224 |
@item |
|
2225 |
TI TSC2102i touchscreen controller / analog-digital converter / Audio |
|
2226 |
CODEC, connected through MicroWire and I@math{^2}S busses |
|
2227 |
@item |
|
2228 |
GPIO-connected matrix keypad |
|
2229 |
@item |
|
2230 |
Secure Digital card connected to OMAP MMC/SD host |
|
2231 |
@item |
|
2232 |
Three on-chip UARTs |
|
2233 |
@end itemize |
|
2234 |
|
|
2211 | 2235 |
A Linux 2.6 test image is available on the QEMU web site. More |
2212 | 2236 |
information is available in the QEMU mailing-list archive. |
2213 | 2237 |
|
Also available in: Unified diff