Commit 026459262747819f90a4056292582661294342ce

Authored by balrog
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
Changelog
... ... @@ -5,7 +5,7 @@
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,6 +16,7 @@
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  
... ...
Makefile.target
... ... @@ -519,7 +519,8 @@ VL_OBJS+= arm-semi.o
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)
... ...
hw/omap.c
... ... @@ -24,8 +24,11 @@
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,15 +3469,15 @@ static void omap_pwl_write(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,15 +3574,15 @@ static void omap_pwt_write(void *opaque, target_phys_addr_t addr,
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,421 +3606,6 @@ static void omap_pwt_init(target_phys_addr_t base, 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,6 +4195,26 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
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;
... ...
hw/omap.h
... ... @@ -475,11 +475,6 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
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,6 +493,13 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
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,6 +563,8 @@ struct omap_mpu_state_s {
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  
... ...
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 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,6 +2209,29 @@ Three on-chip UARTs
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  
... ...