Commit b854bc196f5c4b4e3299c0b0ee63cf828ece9e77
1 parent
e616a7e8
Make accesses with wrong width also work as apparently real hardware allows them…
… when the fault is disabled. Fix DMA register writes if target_phys_addr_t is 64-bit. Make more functions static. A timer hack to make PalmOS run in finite time (uses very short timer periods, much shorter than clocksource tick). Re-calculate internal clock rates on start-up. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3527 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
59 additions
and
20 deletions
hw/omap.c
| @@ -27,38 +27,51 @@ uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) | @@ -27,38 +27,51 @@ uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) | ||
| 27 | uint8_t ret; | 27 | uint8_t ret; |
| 28 | 28 | ||
| 29 | OMAP_8B_REG(addr); | 29 | OMAP_8B_REG(addr); |
| 30 | - cpu_physical_memory_read(addr, &ret, 1); | 30 | + cpu_physical_memory_read(addr, (void *) &ret, 1); |
| 31 | return ret; | 31 | return ret; |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, | 34 | void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, |
| 35 | uint32_t value) | 35 | uint32_t value) |
| 36 | { | 36 | { |
| 37 | + uint8_t val8 = value; | ||
| 38 | + | ||
| 37 | OMAP_8B_REG(addr); | 39 | OMAP_8B_REG(addr); |
| 40 | + cpu_physical_memory_write(addr, (void *) &val8, 1); | ||
| 38 | } | 41 | } |
| 39 | 42 | ||
| 40 | uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr) | 43 | uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr) |
| 41 | { | 44 | { |
| 45 | + uint16_t ret; | ||
| 46 | + | ||
| 42 | OMAP_16B_REG(addr); | 47 | OMAP_16B_REG(addr); |
| 43 | - return 0; | 48 | + cpu_physical_memory_read(addr, (void *) &ret, 2); |
| 49 | + return ret; | ||
| 44 | } | 50 | } |
| 45 | 51 | ||
| 46 | void omap_badwidth_write16(void *opaque, target_phys_addr_t addr, | 52 | void omap_badwidth_write16(void *opaque, target_phys_addr_t addr, |
| 47 | uint32_t value) | 53 | uint32_t value) |
| 48 | { | 54 | { |
| 55 | + uint16_t val16 = value; | ||
| 56 | + | ||
| 49 | OMAP_16B_REG(addr); | 57 | OMAP_16B_REG(addr); |
| 58 | + cpu_physical_memory_write(addr, (void *) &val16, 2); | ||
| 50 | } | 59 | } |
| 51 | 60 | ||
| 52 | uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr) | 61 | uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr) |
| 53 | { | 62 | { |
| 63 | + uint32_t ret; | ||
| 64 | + | ||
| 54 | OMAP_32B_REG(addr); | 65 | OMAP_32B_REG(addr); |
| 55 | - return 0; | 66 | + cpu_physical_memory_read(addr, (void *) &ret, 4); |
| 67 | + return ret; | ||
| 56 | } | 68 | } |
| 57 | 69 | ||
| 58 | void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, | 70 | void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, |
| 59 | uint32_t value) | 71 | uint32_t value) |
| 60 | { | 72 | { |
| 61 | OMAP_32B_REG(addr); | 73 | OMAP_32B_REG(addr); |
| 74 | + cpu_physical_memory_write(addr, (void *) &value, 4); | ||
| 62 | } | 75 | } |
| 63 | 76 | ||
| 64 | /* Interrupt Handlers */ | 77 | /* Interrupt Handlers */ |
| @@ -787,7 +800,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, | @@ -787,7 +800,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, | ||
| 787 | 800 | ||
| 788 | case 0x0a: /* SYS_DMA_CSSA_U_CH0 */ | 801 | case 0x0a: /* SYS_DMA_CSSA_U_CH0 */ |
| 789 | s->ch[ch].addr[0] &= 0x0000ffff; | 802 | s->ch[ch].addr[0] &= 0x0000ffff; |
| 790 | - s->ch[ch].addr[0] |= value << 16; | 803 | + s->ch[ch].addr[0] |= (uint32_t) value << 16; |
| 791 | break; | 804 | break; |
| 792 | 805 | ||
| 793 | case 0x0c: /* SYS_DMA_CDSA_L_CH0 */ | 806 | case 0x0c: /* SYS_DMA_CDSA_L_CH0 */ |
| @@ -797,7 +810,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, | @@ -797,7 +810,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, | ||
| 797 | 810 | ||
| 798 | case 0x0e: /* SYS_DMA_CDSA_U_CH0 */ | 811 | case 0x0e: /* SYS_DMA_CDSA_U_CH0 */ |
| 799 | s->ch[ch].addr[1] &= 0x0000ffff; | 812 | s->ch[ch].addr[1] &= 0x0000ffff; |
| 800 | - s->ch[ch].addr[1] |= value << 16; | 813 | + s->ch[ch].addr[1] |= (uint32_t) value << 16; |
| 801 | break; | 814 | break; |
| 802 | 815 | ||
| 803 | case 0x10: /* SYS_DMA_CEN_CH0 */ | 816 | case 0x10: /* SYS_DMA_CEN_CH0 */ |
| @@ -1033,37 +1046,37 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, | @@ -1033,37 +1046,37 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, | ||
| 1033 | } | 1046 | } |
| 1034 | 1047 | ||
| 1035 | /* DMA ports */ | 1048 | /* DMA ports */ |
| 1036 | -int omap_validate_emiff_addr(struct omap_mpu_state_s *s, | 1049 | +static int omap_validate_emiff_addr(struct omap_mpu_state_s *s, |
| 1037 | target_phys_addr_t addr) | 1050 | target_phys_addr_t addr) |
| 1038 | { | 1051 | { |
| 1039 | return addr >= OMAP_EMIFF_BASE && addr < OMAP_EMIFF_BASE + s->sdram_size; | 1052 | return addr >= OMAP_EMIFF_BASE && addr < OMAP_EMIFF_BASE + s->sdram_size; |
| 1040 | } | 1053 | } |
| 1041 | 1054 | ||
| 1042 | -int omap_validate_emifs_addr(struct omap_mpu_state_s *s, | 1055 | +static int omap_validate_emifs_addr(struct omap_mpu_state_s *s, |
| 1043 | target_phys_addr_t addr) | 1056 | target_phys_addr_t addr) |
| 1044 | { | 1057 | { |
| 1045 | return addr >= OMAP_EMIFS_BASE && addr < OMAP_EMIFF_BASE; | 1058 | return addr >= OMAP_EMIFS_BASE && addr < OMAP_EMIFF_BASE; |
| 1046 | } | 1059 | } |
| 1047 | 1060 | ||
| 1048 | -int omap_validate_imif_addr(struct omap_mpu_state_s *s, | 1061 | +static int omap_validate_imif_addr(struct omap_mpu_state_s *s, |
| 1049 | target_phys_addr_t addr) | 1062 | target_phys_addr_t addr) |
| 1050 | { | 1063 | { |
| 1051 | return addr >= OMAP_IMIF_BASE && addr < OMAP_IMIF_BASE + s->sram_size; | 1064 | return addr >= OMAP_IMIF_BASE && addr < OMAP_IMIF_BASE + s->sram_size; |
| 1052 | } | 1065 | } |
| 1053 | 1066 | ||
| 1054 | -int omap_validate_tipb_addr(struct omap_mpu_state_s *s, | 1067 | +static int omap_validate_tipb_addr(struct omap_mpu_state_s *s, |
| 1055 | target_phys_addr_t addr) | 1068 | target_phys_addr_t addr) |
| 1056 | { | 1069 | { |
| 1057 | return addr >= 0xfffb0000 && addr < 0xffff0000; | 1070 | return addr >= 0xfffb0000 && addr < 0xffff0000; |
| 1058 | } | 1071 | } |
| 1059 | 1072 | ||
| 1060 | -int omap_validate_local_addr(struct omap_mpu_state_s *s, | 1073 | +static int omap_validate_local_addr(struct omap_mpu_state_s *s, |
| 1061 | target_phys_addr_t addr) | 1074 | target_phys_addr_t addr) |
| 1062 | { | 1075 | { |
| 1063 | return addr >= OMAP_LOCALBUS_BASE && addr < OMAP_LOCALBUS_BASE + 0x1000000; | 1076 | return addr >= OMAP_LOCALBUS_BASE && addr < OMAP_LOCALBUS_BASE + 0x1000000; |
| 1064 | } | 1077 | } |
| 1065 | 1078 | ||
| 1066 | -int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s, | 1079 | +static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s, |
| 1067 | target_phys_addr_t addr) | 1080 | target_phys_addr_t addr) |
| 1068 | { | 1081 | { |
| 1069 | return addr >= 0xe1010000 && addr < 0xe1020004; | 1082 | return addr >= 0xe1010000 && addr < 0xe1020004; |
| @@ -1110,9 +1123,23 @@ static inline void omap_timer_update(struct omap_mpu_timer_s *timer) | @@ -1110,9 +1123,23 @@ static inline void omap_timer_update(struct omap_mpu_timer_s *timer) | ||
| 1110 | 1123 | ||
| 1111 | if (timer->enable && timer->st && timer->rate) { | 1124 | if (timer->enable && timer->st && timer->rate) { |
| 1112 | timer->val = timer->reset_val; /* Should skip this on clk enable */ | 1125 | timer->val = timer->reset_val; /* Should skip this on clk enable */ |
| 1113 | - expires = timer->time + muldiv64(timer->val << (timer->ptv + 1), | 1126 | + expires = muldiv64(timer->val << (timer->ptv + 1), |
| 1114 | ticks_per_sec, timer->rate); | 1127 | ticks_per_sec, timer->rate); |
| 1115 | - qemu_mod_timer(timer->timer, expires); | 1128 | + |
| 1129 | + /* If timer expiry would be sooner than in about 1 ms and | ||
| 1130 | + * auto-reload isn't set, then fire immediately. This is a hack | ||
| 1131 | + * to make systems like PalmOS run in acceptable time. PalmOS | ||
| 1132 | + * sets the interval to a very low value and polls the status bit | ||
| 1133 | + * in a busy loop when it wants to sleep just a couple of CPU | ||
| 1134 | + * ticks. */ | ||
| 1135 | + if (expires > (ticks_per_sec >> 10) || timer->ar) | ||
| 1136 | + qemu_mod_timer(timer->timer, timer->time + expires); | ||
| 1137 | + else { | ||
| 1138 | + timer->val = 0; | ||
| 1139 | + timer->st = 0; | ||
| 1140 | + if (timer->it_ena) | ||
| 1141 | + qemu_irq_raise(timer->irq); | ||
| 1142 | + } | ||
| 1116 | } else | 1143 | } else |
| 1117 | qemu_del_timer(timer->timer); | 1144 | qemu_del_timer(timer->timer); |
| 1118 | } | 1145 | } |
| @@ -3502,12 +3529,11 @@ static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | @@ -3502,12 +3529,11 @@ static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | ||
| 3502 | { | 3529 | { |
| 3503 | int iomemtype; | 3530 | int iomemtype; |
| 3504 | 3531 | ||
| 3505 | - s->pwl.base = base; | ||
| 3506 | omap_pwl_reset(s); | 3532 | omap_pwl_reset(s); |
| 3507 | 3533 | ||
| 3508 | iomemtype = cpu_register_io_memory(0, omap_pwl_readfn, | 3534 | iomemtype = cpu_register_io_memory(0, omap_pwl_readfn, |
| 3509 | omap_pwl_writefn, s); | 3535 | omap_pwl_writefn, s); |
| 3510 | - cpu_register_physical_memory(s->pwl.base, 0x800, iomemtype); | 3536 | + cpu_register_physical_memory(base, 0x800, iomemtype); |
| 3511 | 3537 | ||
| 3512 | omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]); | 3538 | omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]); |
| 3513 | } | 3539 | } |
| @@ -3597,13 +3623,12 @@ static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | @@ -3597,13 +3623,12 @@ static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | ||
| 3597 | { | 3623 | { |
| 3598 | int iomemtype; | 3624 | int iomemtype; |
| 3599 | 3625 | ||
| 3600 | - s->pwt.base = base; | ||
| 3601 | s->pwt.clk = clk; | 3626 | s->pwt.clk = clk; |
| 3602 | omap_pwt_reset(s); | 3627 | omap_pwt_reset(s); |
| 3603 | 3628 | ||
| 3604 | iomemtype = cpu_register_io_memory(0, omap_pwt_readfn, | 3629 | iomemtype = cpu_register_io_memory(0, omap_pwt_readfn, |
| 3605 | omap_pwt_writefn, s); | 3630 | omap_pwt_writefn, s); |
| 3606 | - cpu_register_physical_memory(s->pwt.base, 0x800, iomemtype); | 3631 | + cpu_register_physical_memory(base, 0x800, iomemtype); |
| 3607 | } | 3632 | } |
| 3608 | 3633 | ||
| 3609 | /* Real-time Clock module */ | 3634 | /* Real-time Clock module */ |
| @@ -4207,6 +4232,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | @@ -4207,6 +4232,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | ||
| 4207 | * USB Host fffba000 - fffba7ff | 4232 | * USB Host fffba000 - fffba7ff |
| 4208 | * FAC fffba800 - fffbafff | 4233 | * FAC fffba800 - fffbafff |
| 4209 | * HDQ/1-Wire fffbc000 - fffbc7ff | 4234 | * HDQ/1-Wire fffbc000 - fffbc7ff |
| 4235 | + * TIPB switches fffbc800 - fffbcfff | ||
| 4210 | * LED1 fffbd000 - fffbd7ff | 4236 | * LED1 fffbd000 - fffbd7ff |
| 4211 | * LED2 fffbd800 - fffbdfff | 4237 | * LED2 fffbd800 - fffbdfff |
| 4212 | * Mailbox fffcf000 - fffcf7ff | 4238 | * Mailbox fffcf000 - fffcf7ff |
hw/omap.h
| @@ -646,14 +646,23 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, | @@ -646,14 +646,23 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, | ||
| 646 | # define OMAP_RO_REG(paddr) \ | 646 | # define OMAP_RO_REG(paddr) \ |
| 647 | printf("%s: Read-only register " OMAP_FMT_plx "\n", \ | 647 | printf("%s: Read-only register " OMAP_FMT_plx "\n", \ |
| 648 | __FUNCTION__, paddr) | 648 | __FUNCTION__, paddr) |
| 649 | -# define OMAP_8B_REG(paddr) \ | 649 | + |
| 650 | +# define TCMI_VERBOSE 1 | ||
| 651 | + | ||
| 652 | +# ifdef TCMI_VERBOSE | ||
| 653 | +# define OMAP_8B_REG(paddr) \ | ||
| 650 | printf("%s: 8-bit register " OMAP_FMT_plx "\n", \ | 654 | printf("%s: 8-bit register " OMAP_FMT_plx "\n", \ |
| 651 | __FUNCTION__, paddr) | 655 | __FUNCTION__, paddr) |
| 652 | -# define OMAP_16B_REG(paddr) \ | 656 | +# define OMAP_16B_REG(paddr) \ |
| 653 | printf("%s: 16-bit register " OMAP_FMT_plx "\n", \ | 657 | printf("%s: 16-bit register " OMAP_FMT_plx "\n", \ |
| 654 | __FUNCTION__, paddr) | 658 | __FUNCTION__, paddr) |
| 655 | -# define OMAP_32B_REG(paddr) \ | 659 | +# define OMAP_32B_REG(paddr) \ |
| 656 | printf("%s: 32-bit register " OMAP_FMT_plx "\n", \ | 660 | printf("%s: 32-bit register " OMAP_FMT_plx "\n", \ |
| 657 | __FUNCTION__, paddr) | 661 | __FUNCTION__, paddr) |
| 662 | +# else | ||
| 663 | +# define OMAP_8B_REG(paddr) | ||
| 664 | +# define OMAP_16B_REG(paddr) | ||
| 665 | +# define OMAP_32B_REG(paddr) | ||
| 666 | +# endif | ||
| 658 | 667 | ||
| 659 | #endif /* hw_omap_h */ | 668 | #endif /* hw_omap_h */ |
hw/omap1_clk.c
| @@ -742,4 +742,8 @@ void omap_clk_init(struct omap_mpu_state_s *mpu) | @@ -742,4 +742,8 @@ void omap_clk_init(struct omap_mpu_state_s *mpu) | ||
| 742 | j->multiplier = j->multiplier ?: 1; | 742 | j->multiplier = j->multiplier ?: 1; |
| 743 | j ++; | 743 | j ++; |
| 744 | } | 744 | } |
| 745 | + for (j = mpu->clks; count --; j ++) { | ||
| 746 | + omap_clk_update(j); | ||
| 747 | + omap_clk_rate_update(j); | ||
| 748 | + } | ||
| 745 | } | 749 | } |