Commit 026459262747819f90a4056292582661294342ce
1 parent
5c1c390f
Split I^2C controller out of hw/omap.c.
Insert a list of missing memory mappings from OMAP310 datasheet. Add missing "rtc" field for RTC. Correct PWL and PWT register read/write handler pointers. Add a Changelog entry about OMAP emulation. Add a qemu-doc snippet about Palm T|E platform. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3516 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
500 additions
and
427 deletions
Changelog
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau) | 5 | - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau) |
6 | - Several Sparc fixes (Aurelien Jarno, Blue Swirl, Robert Reif) | 6 | - Several Sparc fixes (Aurelien Jarno, Blue Swirl, Robert Reif) |
7 | - MIPS 64-bit FPU support (Thiemo Seufer) | 7 | - MIPS 64-bit FPU support (Thiemo Seufer) |
8 | - - Xscale PDA emulation (Andrzei Zaborowski) | 8 | + - Xscale PDA emulation (Andrzej Zaborowski) |
9 | - ColdFire system emulation (Paul Brook) | 9 | - ColdFire system emulation (Paul Brook) |
10 | - Improved SH4 support (Magnus Damm) | 10 | - Improved SH4 support (Magnus Damm) |
11 | - MIPS64 support (Aurelien Jarno, Thiemo Seufer) | 11 | - MIPS64 support (Aurelien Jarno, Thiemo Seufer) |
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | - SPARC32PLUS execution support (Blue Swirl) | 16 | - SPARC32PLUS execution support (Blue Swirl) |
17 | - MIPS mipssim pequdo machine (Thiemo Seufer) | 17 | - MIPS mipssim pequdo machine (Thiemo Seufer) |
18 | - Strace for Linux userland emulation (Stuart Anderson, Thayne Harbaugh) | 18 | - Strace for Linux userland emulation (Stuart Anderson, Thayne Harbaugh) |
19 | + - OMAP310 MPU emulation plus Palm T|E machine (Andrzej Zaborowski) | ||
19 | 20 | ||
20 | version 0.9.0: | 21 | version 0.9.0: |
21 | 22 |
Makefile.target
@@ -519,7 +519,8 @@ VL_OBJS+= arm-semi.o | @@ -519,7 +519,8 @@ VL_OBJS+= arm-semi.o | ||
519 | VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o | 519 | VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o |
520 | VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o | 520 | VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o |
521 | VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o ecc.o $(AUDIODRV) wm8750.o | 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 | CPPFLAGS += -DHAS_AUDIO | 524 | CPPFLAGS += -DHAS_AUDIO |
524 | endif | 525 | endif |
525 | ifeq ($(TARGET_BASE_ARCH), sh4) | 526 | ifeq ($(TARGET_BASE_ARCH), sh4) |
hw/omap.c
@@ -24,8 +24,11 @@ | @@ -24,8 +24,11 @@ | ||
24 | /* Should signal the TCMI */ | 24 | /* Should signal the TCMI */ |
25 | uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) | 25 | uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) |
26 | { | 26 | { |
27 | + uint8_t ret; | ||
28 | + | ||
27 | OMAP_8B_REG(addr); | 29 | OMAP_8B_REG(addr); |
28 | - return 0; | 30 | + cpu_physical_memory_read(addr, &ret, 1); |
31 | + return ret; | ||
29 | } | 32 | } |
30 | 33 | ||
31 | void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, | 34 | void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, |
@@ -3466,15 +3469,15 @@ static void omap_pwl_write(void *opaque, target_phys_addr_t addr, | @@ -3466,15 +3469,15 @@ static void omap_pwl_write(void *opaque, target_phys_addr_t addr, | ||
3466 | } | 3469 | } |
3467 | 3470 | ||
3468 | static CPUReadMemoryFunc *omap_pwl_readfn[] = { | 3471 | static CPUReadMemoryFunc *omap_pwl_readfn[] = { |
3472 | + omap_pwl_read, | ||
3469 | omap_badwidth_read8, | 3473 | omap_badwidth_read8, |
3470 | omap_badwidth_read8, | 3474 | omap_badwidth_read8, |
3471 | - omap_pwl_read, | ||
3472 | }; | 3475 | }; |
3473 | 3476 | ||
3474 | static CPUWriteMemoryFunc *omap_pwl_writefn[] = { | 3477 | static CPUWriteMemoryFunc *omap_pwl_writefn[] = { |
3478 | + omap_pwl_write, | ||
3475 | omap_badwidth_write8, | 3479 | omap_badwidth_write8, |
3476 | omap_badwidth_write8, | 3480 | omap_badwidth_write8, |
3477 | - omap_pwl_write, | ||
3478 | }; | 3481 | }; |
3479 | 3482 | ||
3480 | void omap_pwl_reset(struct omap_mpu_state_s *s) | 3483 | void omap_pwl_reset(struct omap_mpu_state_s *s) |
@@ -3571,15 +3574,15 @@ static void omap_pwt_write(void *opaque, target_phys_addr_t addr, | @@ -3571,15 +3574,15 @@ static void omap_pwt_write(void *opaque, target_phys_addr_t addr, | ||
3571 | } | 3574 | } |
3572 | 3575 | ||
3573 | static CPUReadMemoryFunc *omap_pwt_readfn[] = { | 3576 | static CPUReadMemoryFunc *omap_pwt_readfn[] = { |
3577 | + omap_pwt_read, | ||
3574 | omap_badwidth_read8, | 3578 | omap_badwidth_read8, |
3575 | omap_badwidth_read8, | 3579 | omap_badwidth_read8, |
3576 | - omap_pwt_read, | ||
3577 | }; | 3580 | }; |
3578 | 3581 | ||
3579 | static CPUWriteMemoryFunc *omap_pwt_writefn[] = { | 3582 | static CPUWriteMemoryFunc *omap_pwt_writefn[] = { |
3583 | + omap_pwt_write, | ||
3580 | omap_badwidth_write8, | 3584 | omap_badwidth_write8, |
3581 | omap_badwidth_write8, | 3585 | omap_badwidth_write8, |
3582 | - omap_pwt_write, | ||
3583 | }; | 3586 | }; |
3584 | 3587 | ||
3585 | void omap_pwt_reset(struct omap_mpu_state_s *s) | 3588 | void omap_pwt_reset(struct omap_mpu_state_s *s) |
@@ -3603,421 +3606,6 @@ static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | @@ -3603,421 +3606,6 @@ static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | ||
3603 | cpu_register_physical_memory(s->pwt.base, 0x800, iomemtype); | 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 | /* Real-time Clock module */ | 3609 | /* Real-time Clock module */ |
4022 | struct omap_rtc_s { | 3610 | struct omap_rtc_s { |
4023 | target_phys_addr_t base; | 3611 | target_phys_addr_t base; |
@@ -4607,6 +4195,26 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | @@ -4607,6 +4195,26 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | ||
4607 | 4195 | ||
4608 | s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER], | 4196 | s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER], |
4609 | omap_findclk(s, "clk32-kHz")); | 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 | qemu_register_reset(omap_mpu_reset, s); | 4218 | qemu_register_reset(omap_mpu_reset, s); |
4611 | 4219 | ||
4612 | return s; | 4220 | return s; |
hw/omap.h
@@ -475,11 +475,6 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base, | @@ -475,11 +475,6 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base, | ||
475 | void omap_uwire_attach(struct omap_uwire_s *s, | 475 | void omap_uwire_attach(struct omap_uwire_s *s, |
476 | struct uwire_slave_s *slave, int chipselect); | 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 | struct omap_rtc_s; | 478 | struct omap_rtc_s; |
484 | struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base, | 479 | struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base, |
485 | qemu_irq *irq, omap_clk clk); | 480 | qemu_irq *irq, omap_clk clk); |
@@ -498,6 +493,13 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, | @@ -498,6 +493,13 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, | ||
498 | void omap_mmc_reset(struct omap_mmc_s *s); | 493 | void omap_mmc_reset(struct omap_mmc_s *s); |
499 | void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover); | 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 | # define cpu_is_omap310(cpu) (cpu->mpu_model == omap310) | 503 | # define cpu_is_omap310(cpu) (cpu->mpu_model == omap310) |
502 | # define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510) | 504 | # define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510) |
503 | # define cpu_is_omap15xx(cpu) \ | 505 | # define cpu_is_omap15xx(cpu) \ |
@@ -561,6 +563,8 @@ struct omap_mpu_state_s { | @@ -561,6 +563,8 @@ struct omap_mpu_state_s { | ||
561 | 563 | ||
562 | struct omap_i2c_s *i2c; | 564 | struct omap_i2c_s *i2c; |
563 | 565 | ||
566 | + struct omap_rtc_s *rtc; | ||
567 | + | ||
564 | /* MPU private TIPB peripherals */ | 568 | /* MPU private TIPB peripherals */ |
565 | struct omap_intr_handler_s *ih[2]; | 569 | struct omap_intr_handler_s *ih[2]; |
566 | 570 |
hw/omap_i2c.c
0 โ 100644
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 | +} |
qemu-doc.texi
@@ -83,6 +83,7 @@ For system emulation, the following hardware targets are supported: | @@ -83,6 +83,7 @@ For system emulation, the following hardware targets are supported: | ||
83 | @item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor) | 83 | @item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor) |
84 | @item Freescale MCF5208EVB (ColdFire V2). | 84 | @item Freescale MCF5208EVB (ColdFire V2). |
85 | @item Arnewsh MCF5206 evaluation board (ColdFire V2). | 85 | @item Arnewsh MCF5206 evaluation board (ColdFire V2). |
86 | +@item Palm Tungsten|E PDA (OMAP310 processor) | ||
86 | @end itemize | 87 | @end itemize |
87 | 88 | ||
88 | For user emulation, x86, PowerPC, ARM, MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported. | 89 | For user emulation, x86, PowerPC, ARM, MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported. |
@@ -2208,6 +2209,29 @@ Three on-chip UARTs | @@ -2208,6 +2209,29 @@ Three on-chip UARTs | ||
2208 | WM8750 audio CODEC on I@math{^2}C and I@math{^2}S busses | 2209 | WM8750 audio CODEC on I@math{^2}C and I@math{^2}S busses |
2209 | @end itemize | 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 | A Linux 2.6 test image is available on the QEMU web site. More | 2235 | A Linux 2.6 test image is available on the QEMU web site. More |
2212 | information is available in the QEMU mailing-list archive. | 2236 | information is available in the QEMU mailing-list archive. |
2213 | 2237 |