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); | ... | ... |