Revision 4a2c8ac2 hw/omap.c
b/hw/omap.c | ||
---|---|---|
3603 | 3603 |
cpu_register_physical_memory(s->pwt.base, 0x800, iomemtype); |
3604 | 3604 |
} |
3605 | 3605 |
|
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 |
|
|
3606 | 4021 |
/* General chip reset */ |
3607 | 4022 |
static void omap_mpu_reset(void *opaque) |
3608 | 4023 |
{ |
... | ... | |
3634 | 4049 |
omap_gpio_reset(mpu->gpio); |
3635 | 4050 |
omap_uwire_reset(mpu->microwire); |
3636 | 4051 |
omap_pwl_reset(mpu); |
4052 |
omap_pwt_reset(mpu); |
|
4053 |
omap_i2c_reset(mpu->i2c); |
|
3637 | 4054 |
cpu_reset(mpu->env); |
3638 | 4055 |
} |
3639 | 4056 |
|
... | ... | |
3758 | 4175 |
omap_pwl_init(0xfffb5800, s, omap_findclk(s, "clk32-kHz")); |
3759 | 4176 |
omap_pwt_init(0xfffb6000, s, omap_findclk(s, "xtal_osc_12m")); |
3760 | 4177 |
|
4178 |
s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C], |
|
4179 |
&s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck")); |
|
4180 |
|
|
3761 | 4181 |
qemu_register_reset(omap_mpu_reset, s); |
3762 | 4182 |
|
3763 | 4183 |
return s; |
Also available in: Unified diff