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 | 403 | target_phys_addr_t base; |
| 404 | 404 | omap_clk clk; |
| 405 | 405 | int64_t delay; |
| 406 | + uint32_t drq; | |
| 406 | 407 | |
| 407 | 408 | uint16_t gcr; |
| 408 | 409 | int run_count; |
| ... | ... | @@ -511,7 +512,7 @@ next_channel: |
| 511 | 512 | if (request > 0) |
| 512 | 513 | s->ch[channel].status |= 0x40; /* External request */ |
| 513 | 514 | |
| 514 | - if (s->delay) | |
| 515 | + if (s->delay && !qemu_timer_pending(s->tm)) | |
| 515 | 516 | qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay); |
| 516 | 517 | |
| 517 | 518 | if (request > 0) { |
| ... | ... | @@ -593,7 +594,8 @@ static void omap_dma_channel_run(struct omap_dma_s *s) |
| 593 | 594 | if (s->ch[ch].interrupts & 0x08) |
| 594 | 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 | 599 | s->ch[ch].status &= ~0x40; |
| 598 | 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 | 609 | if (s->ch[ch].interrupts & 0x04) |
| 608 | 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 | 614 | s->ch[ch].status &= ~0x40; |
| 612 | 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 | 753 | s->ch[ch].running = 1; |
| 751 | 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 | 757 | omap_dma_request_run(s, ch, 0); |
| 755 | 758 | } else { |
| 756 | 759 | s->ch[ch].running = 0; |
| ... | ... | @@ -949,9 +952,14 @@ static CPUWriteMemoryFunc *omap_dma_writefn[] = { |
| 949 | 952 | static void omap_dma_request(void *opaque, int drq, int req) |
| 950 | 953 | { |
| 951 | 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 | 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 | 982 | |
| 975 | 983 | qemu_del_timer(s->tm); |
| 976 | 984 | s->gcr = 0x0004; |
| 985 | + s->drq = 0x00000000; | |
| 977 | 986 | s->run_count = 0; |
| 978 | 987 | s->lcd_ch.src = emiff; |
| 979 | 988 | s->lcd_ch.condition = 0; |
| ... | ... | @@ -1002,6 +1011,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, |
| 1002 | 1011 | omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]); |
| 1003 | 1012 | mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 32); |
| 1004 | 1013 | omap_dma_reset(s); |
| 1014 | + omap_dma_clk_update(s, 0, 1); | |
| 1005 | 1015 | |
| 1006 | 1016 | iomemtype = cpu_register_io_memory(0, omap_dma_readfn, |
| 1007 | 1017 | omap_dma_writefn, s); | ... | ... |