Commit 1af2b62d123ae5601eb44786faf3be17aed1b2b2
1 parent
cfa0b71d
OMAP DMA input signals must be level-triggered.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3096 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
17 additions
and
7 deletions
hw/omap.c
| @@ -403,6 +403,7 @@ struct omap_dma_s { | @@ -403,6 +403,7 @@ struct omap_dma_s { | ||
| 403 | target_phys_addr_t base; | 403 | target_phys_addr_t base; |
| 404 | omap_clk clk; | 404 | omap_clk clk; |
| 405 | int64_t delay; | 405 | int64_t delay; |
| 406 | + uint32_t drq; | ||
| 406 | 407 | ||
| 407 | uint16_t gcr; | 408 | uint16_t gcr; |
| 408 | int run_count; | 409 | int run_count; |
| @@ -511,7 +512,7 @@ next_channel: | @@ -511,7 +512,7 @@ next_channel: | ||
| 511 | if (request > 0) | 512 | if (request > 0) |
| 512 | s->ch[channel].status |= 0x40; /* External request */ | 513 | s->ch[channel].status |= 0x40; /* External request */ |
| 513 | 514 | ||
| 514 | - if (s->delay) | 515 | + if (s->delay && !qemu_timer_pending(s->tm)) |
| 515 | qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay); | 516 | qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay); |
| 516 | 517 | ||
| 517 | if (request > 0) { | 518 | if (request > 0) { |
| @@ -593,7 +594,8 @@ static void omap_dma_channel_run(struct omap_dma_s *s) | @@ -593,7 +594,8 @@ static void omap_dma_channel_run(struct omap_dma_s *s) | ||
| 593 | if (s->ch[ch].interrupts & 0x08) | 594 | if (s->ch[ch].interrupts & 0x08) |
| 594 | s->ch[ch].status |= 0x08; | 595 | s->ch[ch].status |= 0x08; |
| 595 | 596 | ||
| 596 | - if (s->ch[ch].sync && s->ch[ch].fs) { | 597 | + if (s->ch[ch].sync && s->ch[ch].fs && |
| 598 | + !(s->drq & (1 << s->ch[ch].sync))) { | ||
| 597 | s->ch[ch].status &= ~0x40; | 599 | s->ch[ch].status &= ~0x40; |
| 598 | omap_dma_request_stop(s, ch); | 600 | omap_dma_request_stop(s, ch); |
| 599 | } | 601 | } |
| @@ -607,7 +609,8 @@ static void omap_dma_channel_run(struct omap_dma_s *s) | @@ -607,7 +609,8 @@ static void omap_dma_channel_run(struct omap_dma_s *s) | ||
| 607 | if (s->ch[ch].interrupts & 0x04) | 609 | if (s->ch[ch].interrupts & 0x04) |
| 608 | s->ch[ch].status |= 0x04; | 610 | s->ch[ch].status |= 0x04; |
| 609 | 611 | ||
| 610 | - if (s->ch[ch].sync && !s->ch[ch].fs) { | 612 | + if (s->ch[ch].sync && !s->ch[ch].fs && |
| 613 | + !(s->drq & (1 << s->ch[ch].sync))) { | ||
| 611 | s->ch[ch].status &= ~0x40; | 614 | s->ch[ch].status &= ~0x40; |
| 612 | omap_dma_request_stop(s, ch); | 615 | omap_dma_request_stop(s, ch); |
| 613 | } | 616 | } |
| @@ -750,7 +753,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, | @@ -750,7 +753,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, | ||
| 750 | s->ch[ch].running = 1; | 753 | s->ch[ch].running = 1; |
| 751 | omap_dma_channel_load(s, ch); | 754 | omap_dma_channel_load(s, ch); |
| 752 | } | 755 | } |
| 753 | - if (!s->ch[ch].sync) | 756 | + if (!s->ch[ch].sync || (s->drq & (1 << s->ch[ch].sync))) |
| 754 | omap_dma_request_run(s, ch, 0); | 757 | omap_dma_request_run(s, ch, 0); |
| 755 | } else { | 758 | } else { |
| 756 | s->ch[ch].running = 0; | 759 | s->ch[ch].running = 0; |
| @@ -949,9 +952,14 @@ static CPUWriteMemoryFunc *omap_dma_writefn[] = { | @@ -949,9 +952,14 @@ static CPUWriteMemoryFunc *omap_dma_writefn[] = { | ||
| 949 | static void omap_dma_request(void *opaque, int drq, int req) | 952 | static void omap_dma_request(void *opaque, int drq, int req) |
| 950 | { | 953 | { |
| 951 | struct omap_dma_s *s = (struct omap_dma_s *) opaque; | 954 | struct omap_dma_s *s = (struct omap_dma_s *) opaque; |
| 952 | - /* All the request pins are edge triggered. */ | ||
| 953 | - if (req) | ||
| 954 | - omap_dma_request_run(s, 0, drq); | 955 | + /* The request pins are level triggered. */ |
| 956 | + if (req) { | ||
| 957 | + if (~s->drq & (1 << drq)) { | ||
| 958 | + s->drq |= 1 << drq; | ||
| 959 | + omap_dma_request_run(s, 0, drq); | ||
| 960 | + } | ||
| 961 | + } else | ||
| 962 | + s->drq &= ~(1 << drq); | ||
| 955 | } | 963 | } |
| 956 | 964 | ||
| 957 | static void omap_dma_clk_update(void *opaque, int line, int on) | 965 | static void omap_dma_clk_update(void *opaque, int line, int on) |
| @@ -974,6 +982,7 @@ static void omap_dma_reset(struct omap_dma_s *s) | @@ -974,6 +982,7 @@ static void omap_dma_reset(struct omap_dma_s *s) | ||
| 974 | 982 | ||
| 975 | qemu_del_timer(s->tm); | 983 | qemu_del_timer(s->tm); |
| 976 | s->gcr = 0x0004; | 984 | s->gcr = 0x0004; |
| 985 | + s->drq = 0x00000000; | ||
| 977 | s->run_count = 0; | 986 | s->run_count = 0; |
| 978 | s->lcd_ch.src = emiff; | 987 | s->lcd_ch.src = emiff; |
| 979 | s->lcd_ch.condition = 0; | 988 | s->lcd_ch.condition = 0; |
| @@ -1002,6 +1011,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, | @@ -1002,6 +1011,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, | ||
| 1002 | omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]); | 1011 | omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]); |
| 1003 | mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 32); | 1012 | mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 32); |
| 1004 | omap_dma_reset(s); | 1013 | omap_dma_reset(s); |
| 1014 | + omap_dma_clk_update(s, 0, 1); | ||
| 1005 | 1015 | ||
| 1006 | iomemtype = cpu_register_io_memory(0, omap_dma_readfn, | 1016 | iomemtype = cpu_register_io_memory(0, omap_dma_readfn, |
| 1007 | omap_dma_writefn, s); | 1017 | omap_dma_writefn, s); |