Commit 089b7c0a4c2a0b0953ed4323f893eb5af2ca4e2c

Authored by balrog
1 parent 7eb0c8e8

OMAP DMA 3.2 support by Lauro Ramos Venancio.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3786 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 949 additions and 248 deletions
hw/omap.c
... ... @@ -402,38 +402,50 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
402 402 }
403 403  
404 404 /* OMAP1 DMA module */
405   -typedef enum {
406   - constant = 0,
407   - post_incremented,
408   - single_index,
409   - double_index,
410   -} omap_dma_addressing_t;
411   -
412 405 struct omap_dma_channel_s {
  406 + /* transfer data */
413 407 int burst[2];
414 408 int pack[2];
415 409 enum omap_dma_port port[2];
416 410 target_phys_addr_t addr[2];
417 411 omap_dma_addressing_t mode[2];
  412 + uint16_t elements;
  413 + uint16_t frames;
  414 + int16_t frame_index[2];
  415 + int16_t element_index[2];
418 416 int data_type;
  417 +
  418 + /* transfer type */
  419 + int transparent_copy;
  420 + int constant_fill;
  421 + uint32_t color;
  422 +
  423 + /* auto init and linked channel data */
419 424 int end_prog;
420 425 int repeat;
421 426 int auto_init;
422   - int priority;
423   - int fs;
424   - int sync;
425   - int running;
  427 + int link_enabled;
  428 + int link_next_ch;
  429 +
  430 + /* interruption data */
426 431 int interrupts;
427 432 int status;
428   - int signalled;
429   - int post_sync;
430   - int transfer;
431   - uint16_t elements;
432   - uint16_t frames;
433   - uint16_t frame_index;
434   - uint16_t element_index;
  433 +
  434 + /* state data */
  435 + int active;
  436 + int enable;
  437 + int sync;
  438 + int pending_request;
  439 + int waiting_end_prog;
435 440 uint16_t cpc;
436 441  
  442 + /* sync type */
  443 + int fs;
  444 + int bs;
  445 +
  446 + /* compatibility */
  447 + int omap_3_1_compatible_disable;
  448 +
437 449 struct omap_dma_reg_set_s {
438 450 target_phys_addr_t src, dest;
439 451 int frame;
... ... @@ -443,16 +455,23 @@ struct omap_dma_channel_s {
443 455 int frames;
444 456 int elements;
445 457 } active_set;
  458 +
  459 + /* unused parameters */
  460 + int priority;
  461 + int interleave_disabled;
  462 + int type;
446 463 };
447 464  
448 465 struct omap_dma_s {
449   - qemu_irq *ih;
  466 + qemu_irq irqs[16];
450 467 QEMUTimer *tm;
451 468 struct omap_mpu_state_s *mpu;
452 469 target_phys_addr_t base;
453 470 omap_clk clk;
454 471 int64_t delay;
455 472 uint32_t drq;
  473 + enum omap_dma_model model;
  474 + int omap_3_1_mapping_disabled;
456 475  
457 476 uint16_t gcr;
458 477 int run_count;
... ... @@ -462,27 +481,55 @@ struct omap_dma_s {
462 481 struct omap_dma_lcd_channel_s lcd_ch;
463 482 };
464 483  
  484 +/* Interrupts */
  485 +#define TIMEOUT_INTR (1 << 0)
  486 +#define EVENT_DROP_INTR (1 << 1)
  487 +#define HALF_FRAME_INTR (1 << 2)
  488 +#define END_FRAME_INTR (1 << 3)
  489 +#define LAST_FRAME_INTR (1 << 4)
  490 +#define END_BLOCK_INTR (1 << 5)
  491 +#define SYNC (1 << 6)
  492 +
  493 +static int omap_dma_get_sibling_channel(struct omap_dma_s *s, int channel)
  494 +{
  495 + if (s->omap_3_1_mapping_disabled)
  496 + return -1;
  497 + switch (channel) {
  498 + case 0 ... 2:
  499 + return channel + 6;
  500 + case 6 ... 8:
  501 + return channel % 6;
  502 + }
  503 + return -1;
  504 +}
  505 +
465 506 static void omap_dma_interrupts_update(struct omap_dma_s *s)
466 507 {
467   - /* First three interrupts are shared between two channels each. */
468   - qemu_set_irq(s->ih[OMAP_INT_DMA_CH0_6],
469   - (s->ch[0].status | s->ch[6].status) & 0x3f);
470   - qemu_set_irq(s->ih[OMAP_INT_DMA_CH1_7],
471   - (s->ch[1].status | s->ch[7].status) & 0x3f);
472   - qemu_set_irq(s->ih[OMAP_INT_DMA_CH2_8],
473   - (s->ch[2].status | s->ch[8].status) & 0x3f);
474   - qemu_set_irq(s->ih[OMAP_INT_DMA_CH3],
475   - (s->ch[3].status) & 0x3f);
476   - qemu_set_irq(s->ih[OMAP_INT_DMA_CH4],
477   - (s->ch[4].status) & 0x3f);
478   - qemu_set_irq(s->ih[OMAP_INT_DMA_CH5],
479   - (s->ch[5].status) & 0x3f);
  508 + int i, sibiling, raise;
  509 +
  510 + if (s->omap_3_1_mapping_disabled) {
  511 + for (i = 0; i < s->chans; i ++) {
  512 + if (s->ch[i].status)
  513 + qemu_irq_raise(s->irqs[i]);
  514 + }
  515 + } else {
  516 + /* First three interrupts are shared between two channels each. */
  517 + for (i = 0; i < 6; i ++) {
  518 + raise = s->ch[i].status;
  519 + sibiling = omap_dma_get_sibling_channel(s, i);
  520 + if (sibiling != -1)
  521 + raise |= s->ch[sibiling].status;
  522 + if (raise)
  523 + qemu_irq_raise(s->irqs[i]);
  524 + }
  525 + }
480 526 }
481 527  
482 528 static void omap_dma_channel_load(struct omap_dma_s *s, int ch)
483 529 {
484 530 struct omap_dma_reg_set_s *a = &s->ch[ch].active_set;
485 531 int i;
  532 + int omap_3_1 = !s->ch[ch].omap_3_1_compatible_disable;
486 533  
487 534 /*
488 535 * TODO: verify address ranges and alignment
... ... @@ -513,71 +560,126 @@ static void omap_dma_channel_load(struct omap_dma_s *s, int ch)
513 560 break;
514 561 case single_index:
515 562 a->elem_delta[i] = s->ch[ch].data_type +
516   - s->ch[ch].element_index - 1;
517   - if (s->ch[ch].element_index > 0x7fff)
518   - a->elem_delta[i] -= 0x10000;
  563 + s->ch[ch].element_index[omap_3_1 ? 0 : i] - 1;
519 564 a->frame_delta[i] = 0;
520 565 break;
521 566 case double_index:
522 567 a->elem_delta[i] = s->ch[ch].data_type +
523   - s->ch[ch].element_index - 1;
524   - if (s->ch[ch].element_index > 0x7fff)
525   - a->elem_delta[i] -= 0x10000;
526   - a->frame_delta[i] = s->ch[ch].frame_index -
527   - s->ch[ch].element_index;
528   - if (s->ch[ch].frame_index > 0x7fff)
529   - a->frame_delta[i] -= 0x10000;
  568 + s->ch[ch].element_index[omap_3_1 ? 0 : i] - 1;
  569 + a->frame_delta[i] = s->ch[ch].frame_index[omap_3_1 ? 0 : i] -
  570 + s->ch[ch].element_index[omap_3_1 ? 0 : i];
530 571 break;
531 572 default:
532 573 break;
533 574 }
534 575 }
535 576  
536   -static inline void omap_dma_request_run(struct omap_dma_s *s,
537   - int channel, int request)
  577 +static void omap_dma_activate_channel(struct omap_dma_s *s, int channel)
538 578 {
539   -next_channel:
540   - if (request > 0)
541   - for (; channel < 9; channel ++)
542   - if (s->ch[channel].sync == request && s->ch[channel].running)
543   - break;
544   - if (channel >= 9)
  579 + if (!s->ch[channel].active) {
  580 + s->ch[channel].active = 1;
  581 + if (s->ch[channel].sync)
  582 + s->ch[channel].status |= SYNC;
  583 + s->run_count ++;
  584 + }
  585 +
  586 + if (s->delay && !qemu_timer_pending(s->tm))
  587 + qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
  588 +}
  589 +
  590 +static void omap_dma_deactivate_channel(struct omap_dma_s *s, int channel)
  591 +{
  592 + /* Update cpc */
  593 + s->ch[channel].cpc = s->ch[channel].active_set.dest & 0xffff;
  594 +
  595 + if (s->ch[channel].pending_request &&
  596 + !s->ch[channel].waiting_end_prog) {
  597 + /* Don't deactivate the channel */
  598 + s->ch[channel].pending_request = 0;
545 599 return;
  600 + }
546 601  
547   - if (s->ch[channel].transfer) {
548   - if (request > 0) {
549   - s->ch[channel ++].post_sync = request;
550   - goto next_channel;
551   - }
552   - s->ch[channel].status |= 0x02; /* Synchronisation drop */
553   - omap_dma_interrupts_update(s);
  602 + /* Don't deactive the channel if it is synchronized and the DMA request is
  603 + active */
  604 + if (s->ch[channel].sync && (s->drq & (1 << s->ch[channel].sync)))
554 605 return;
  606 +
  607 + if (s->ch[channel].active) {
  608 + s->ch[channel].active = 0;
  609 + s->ch[channel].status &= ~SYNC;
  610 + s->run_count --;
555 611 }
556 612  
557   - if (!s->ch[channel].signalled)
558   - s->run_count ++;
559   - s->ch[channel].signalled = 1;
  613 + if (!s->run_count)
  614 + qemu_del_timer(s->tm);
  615 +}
560 616  
561   - if (request > 0)
562   - s->ch[channel].status |= 0x40; /* External request */
  617 +static void omap_dma_enable_channel(struct omap_dma_s *s, int channel)
  618 +{
  619 + if (!s->ch[channel].enable) {
  620 + s->ch[channel].enable = 1;
  621 + s->ch[channel].waiting_end_prog = 0;
  622 + omap_dma_channel_load(s, channel);
  623 + if ((!s->ch[channel].sync) || (s->drq & (1 << s->ch[channel].sync)))
  624 + omap_dma_activate_channel(s, channel);
  625 + }
  626 +}
563 627  
564   - if (s->delay && !qemu_timer_pending(s->tm))
565   - qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
  628 +static void omap_dma_disable_channel(struct omap_dma_s *s, int channel)
  629 +{
  630 + if (s->ch[channel].enable) {
  631 + s->ch[channel].enable = 0;
  632 + /* Discard any pending request */
  633 + s->ch[channel].pending_request = 0;
  634 + omap_dma_deactivate_channel(s, channel);
  635 + }
  636 +}
566 637  
567   - if (request > 0) {
568   - channel ++;
569   - goto next_channel;
  638 +static void omap_dma_channel_end_prog(struct omap_dma_s *s, int channel)
  639 +{
  640 + if (s->ch[channel].waiting_end_prog) {
  641 + s->ch[channel].waiting_end_prog = 0;
  642 + if (!s->ch[channel].sync || s->ch[channel].pending_request) {
  643 + s->ch[channel].pending_request = 0;
  644 + omap_dma_activate_channel(s, channel);
  645 + }
570 646 }
571 647 }
572 648  
573   -static inline void omap_dma_request_stop(struct omap_dma_s *s, int channel)
  649 +static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s)
574 650 {
575   - if (s->ch[channel].signalled)
576   - s->run_count --;
577   - s->ch[channel].signalled = 0;
  651 + s->omap_3_1_mapping_disabled = 0;
  652 + s->chans = 9;
  653 +}
578 654  
579   - if (!s->run_count)
580   - qemu_del_timer(s->tm);
  655 +static void omap_dma_disable_3_1_mapping(struct omap_dma_s *s)
  656 +{
  657 + s->omap_3_1_mapping_disabled = 1;
  658 + s->chans = 16;
  659 +}
  660 +
  661 +static void omap_dma_process_request(struct omap_dma_s *s, int request)
  662 +{
  663 + int channel;
  664 + int drop_event = 0;
  665 +
  666 + for (channel = 0; channel < s->chans; channel ++) {
  667 + if (s->ch[channel].enable && s->ch[channel].sync == request) {
  668 + if (!s->ch[channel].active)
  669 + omap_dma_activate_channel(s, channel);
  670 + else if (!s->ch[channel].pending_request)
  671 + s->ch[channel].pending_request = 1;
  672 + else {
  673 + /* Request collision */
  674 + /* Second request received while processing other request */
  675 + s->ch[channel].status |= EVENT_DROP_INTR;
  676 + drop_event = 1;
  677 + }
  678 + }
  679 + }
  680 +
  681 + if (drop_event)
  682 + omap_dma_interrupts_update(s);
581 683 }
582 684  
583 685 static void omap_dma_channel_run(struct omap_dma_s *s)
... ... @@ -588,97 +690,101 @@ static void omap_dma_channel_run(struct omap_dma_s *s)
588 690 struct omap_dma_port_if_s *src_p, *dest_p;
589 691 struct omap_dma_reg_set_s *a;
590 692  
591   - for (ch = 0; ch < 9; ch ++) {
  693 + for (ch = 0; ch < s->chans; ch ++) {
  694 + if (!s->ch[ch].active)
  695 + continue;
  696 +
592 697 a = &s->ch[ch].active_set;
593 698  
594 699 src_p = &s->mpu->port[s->ch[ch].port[0]];
595 700 dest_p = &s->mpu->port[s->ch[ch].port[1]];
596   - if (s->ch[ch].signalled && (!src_p->addr_valid(s->mpu, a->src) ||
597   - !dest_p->addr_valid(s->mpu, a->dest))) {
  701 + if ((!s->ch[ch].constant_fill && !src_p->addr_valid(s->mpu, a->src)) ||
  702 + (!dest_p->addr_valid(s->mpu, a->dest))) {
598 703 #if 0
599 704 /* Bus time-out */
600   - if (s->ch[ch].interrupts & 0x01)
601   - s->ch[ch].status |= 0x01;
602   - omap_dma_request_stop(s, ch);
  705 + if (s->ch[ch].interrupts & TIMEOUT_INTR)
  706 + s->ch[ch].status |= TIMEOUT_INTR;
  707 + omap_dma_deactivate_channel(s, ch);
603 708 continue;
604 709 #endif
605 710 printf("%s: Bus time-out in DMA%i operation\n", __FUNCTION__, ch);
606 711 }
607 712  
608 713 status = s->ch[ch].status;
609   - while (status == s->ch[ch].status && s->ch[ch].signalled) {
  714 + while (status == s->ch[ch].status && s->ch[ch].active) {
610 715 /* Transfer a single element */
611   - s->ch[ch].transfer = 1;
612   - cpu_physical_memory_read(a->src, value, s->ch[ch].data_type);
613   - cpu_physical_memory_write(a->dest, value, s->ch[ch].data_type);
614   - s->ch[ch].transfer = 0;
  716 + /* FIXME: check the endianness */
  717 + if (!s->ch[ch].constant_fill)
  718 + cpu_physical_memory_read(a->src, value, s->ch[ch].data_type);
  719 + else
  720 + *(uint32_t *) value = s->ch[ch].color;
  721 +
  722 + if (!s->ch[ch].transparent_copy ||
  723 + *(uint32_t *) value != s->ch[ch].color)
  724 + cpu_physical_memory_write(a->dest, value, s->ch[ch].data_type);
615 725  
616 726 a->src += a->elem_delta[0];
617 727 a->dest += a->elem_delta[1];
618 728 a->element ++;
619 729  
620   - /* Check interrupt conditions */
  730 + /* If the channel is element synchronized, deactivate it */
  731 + if (s->ch[ch].sync && !s->ch[ch].fs && !s->ch[ch].bs)
  732 + omap_dma_deactivate_channel(s, ch);
  733 +
  734 + /* If it is the last frame, set the LAST_FRAME interrupt */
  735 + if (a->element == 1 && a->frame == a->frames - 1)
  736 + if (s->ch[ch].interrupts & LAST_FRAME_INTR)
  737 + s->ch[ch].status |= LAST_FRAME_INTR;
  738 +
  739 + /* If the half of the frame was reached, set the HALF_FRAME
  740 + interrupt */
  741 + if (a->element == (a->elements >> 1))
  742 + if (s->ch[ch].interrupts & HALF_FRAME_INTR)
  743 + s->ch[ch].status |= HALF_FRAME_INTR;
  744 +
621 745 if (a->element == a->elements) {
  746 + /* End of Frame */
622 747 a->element = 0;
623 748 a->src += a->frame_delta[0];
624 749 a->dest += a->frame_delta[1];
625 750 a->frame ++;
626 751  
627   - if (a->frame == a->frames) {
628   - if (!s->ch[ch].repeat || !s->ch[ch].auto_init)
629   - s->ch[ch].running = 0;
  752 + /* If the channel is frame synchronized, deactivate it */
  753 + if (s->ch[ch].sync && s->ch[ch].fs)
  754 + omap_dma_deactivate_channel(s, ch);
630 755  
631   - if (s->ch[ch].auto_init &&
632   - (s->ch[ch].repeat ||
633   - s->ch[ch].end_prog))
634   - omap_dma_channel_load(s, ch);
  756 + /* If the channel is async, update cpc */
  757 + if (!s->ch[ch].sync)
  758 + s->ch[ch].cpc = a->dest & 0xffff;
635 759  
636   - if (s->ch[ch].interrupts & 0x20)
637   - s->ch[ch].status |= 0x20;
  760 + /* Set the END_FRAME interrupt */
  761 + if (s->ch[ch].interrupts & END_FRAME_INTR)
  762 + s->ch[ch].status |= END_FRAME_INTR;
638 763  
639   - if (!s->ch[ch].sync)
640   - omap_dma_request_stop(s, ch);
641   - }
642   -
643   - if (s->ch[ch].interrupts & 0x08)
644   - s->ch[ch].status |= 0x08;
645   -
646   - if (s->ch[ch].sync && s->ch[ch].fs &&
647   - !(s->drq & (1 << s->ch[ch].sync))) {
648   - s->ch[ch].status &= ~0x40;
649   - omap_dma_request_stop(s, ch);
  764 + if (a->frame == a->frames) {
  765 + /* End of Block */
  766 + /* Disable the channel */
  767 +
  768 + if (s->ch[ch].omap_3_1_compatible_disable) {
  769 + omap_dma_disable_channel(s, ch);
  770 + if (s->ch[ch].link_enabled)
  771 + omap_dma_enable_channel(s, s->ch[ch].link_next_ch);
  772 + } else {
  773 + if (!s->ch[ch].auto_init)
  774 + omap_dma_disable_channel(s, ch);
  775 + else if (s->ch[ch].repeat || s->ch[ch].end_prog)
  776 + omap_dma_channel_load(s, ch);
  777 + else {
  778 + s->ch[ch].waiting_end_prog = 1;
  779 + omap_dma_deactivate_channel(s, ch);
  780 + }
  781 + }
  782 +
  783 + if (s->ch[ch].interrupts & END_BLOCK_INTR)
  784 + s->ch[ch].status |= END_BLOCK_INTR;
650 785 }
651 786 }
652   -
653   - if (a->element == 1 && a->frame == a->frames - 1)
654   - if (s->ch[ch].interrupts & 0x10)
655   - s->ch[ch].status |= 0x10;
656   -
657   - if (a->element == (a->elements >> 1))
658   - if (s->ch[ch].interrupts & 0x04)
659   - s->ch[ch].status |= 0x04;
660   -
661   - if (s->ch[ch].sync && !s->ch[ch].fs &&
662   - !(s->drq & (1 << s->ch[ch].sync))) {
663   - s->ch[ch].status &= ~0x40;
664   - omap_dma_request_stop(s, ch);
665   - }
666   -
667   - /*
668   - * Process requests made while the element was
669   - * being transferred.
670   - */
671   - if (s->ch[ch].post_sync) {
672   - omap_dma_request_run(s, 0, s->ch[ch].post_sync);
673   - s->ch[ch].post_sync = 0;
674   - }
675   -
676   -#if 0
677   - break;
678   -#endif
679 787 }
680   -
681   - s->ch[ch].cpc = a->dest & 0x0000ffff;
682 788 }
683 789  
684 790 omap_dma_interrupts_update(s);
... ... @@ -686,8 +792,29 @@ static void omap_dma_channel_run(struct omap_dma_s *s)
686 792 qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
687 793 }
688 794  
689   -static int omap_dma_ch_reg_read(struct omap_dma_s *s,
690   - int ch, int reg, uint16_t *value) {
  795 +static void omap_dma_reset(struct omap_dma_s *s)
  796 +{
  797 + int i;
  798 +
  799 + qemu_del_timer(s->tm);
  800 + s->gcr = 0x0004;
  801 + s->drq = 0x00000000;
  802 + s->run_count = 0;
  803 + s->lcd_ch.src = emiff;
  804 + s->lcd_ch.condition = 0;
  805 + s->lcd_ch.interrupts = 0;
  806 + s->lcd_ch.dual = 0;
  807 + omap_dma_enable_3_1_mapping(s);
  808 + memset(s->ch, 0, sizeof(s->ch));
  809 + for (i = 0; i < s->chans; i ++)
  810 + s->ch[i].interrupts = 0x0003;
  811 +}
  812 +
  813 +static int omap_dma_ch_reg_read(struct omap_dma_s *s, int ch, int reg,
  814 + uint16_t *value)
  815 +{
  816 + int sibling;
  817 +
691 818 switch (reg) {
692 819 case 0x00: /* SYS_DMA_CSDP_CH0 */
693 820 *value = (s->ch[ch].burst[1] << 14) |
... ... @@ -700,12 +827,16 @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s,
700 827 break;
701 828  
702 829 case 0x02: /* SYS_DMA_CCR_CH0 */
703   - *value = (s->ch[ch].mode[1] << 14) |
  830 + if (s->model == omap_dma_3_1)
  831 + *value = 0 << 10; /* FIFO_FLUSH bit */
  832 + else
  833 + *value = s->ch[ch].omap_3_1_compatible_disable << 10;
  834 + *value |= (s->ch[ch].mode[1] << 14) |
704 835 (s->ch[ch].mode[0] << 12) |
705 836 (s->ch[ch].end_prog << 11) |
706 837 (s->ch[ch].repeat << 9) |
707 838 (s->ch[ch].auto_init << 8) |
708   - (s->ch[ch].running << 7) |
  839 + (s->ch[ch].enable << 7) |
709 840 (s->ch[ch].priority << 6) |
710 841 (s->ch[ch].fs << 5) | s->ch[ch].sync;
711 842 break;
... ... @@ -715,10 +846,18 @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s,
715 846 break;
716 847  
717 848 case 0x06: /* SYS_DMA_CSR_CH0 */
718   - /* FIXME: shared CSR for channels sharing the interrupts */
  849 + sibling = omap_dma_get_sibling_channel(s, ch);
719 850 *value = s->ch[ch].status;
720   - s->ch[ch].status &= 0x40;
721   - omap_dma_interrupts_update(s);
  851 + s->ch[ch].status &= SYNC;
  852 + if (sibling != -1) {
  853 + *value |= (s->ch[sibling].status & 0x3f) << 6;
  854 + s->ch[sibling].status &= SYNC;
  855 + if (sibling < ch) {
  856 + qemu_irq_lower(s->irqs[sibling]);
  857 + break;
  858 + }
  859 + }
  860 + qemu_irq_lower(s->irqs[ch]);
722 861 break;
723 862  
724 863 case 0x08: /* SYS_DMA_CSSA_L_CH0 */
... ... @@ -746,15 +885,54 @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s,
746 885 break;
747 886  
748 887 case 0x14: /* SYS_DMA_CFI_CH0 */
749   - *value = s->ch[ch].frame_index;
  888 + *value = s->ch[ch].frame_index[0];
750 889 break;
751 890  
752 891 case 0x16: /* SYS_DMA_CEI_CH0 */
753   - *value = s->ch[ch].element_index;
  892 + *value = s->ch[ch].element_index[0];
  893 + break;
  894 +
  895 + case 0x18: /* SYS_DMA_CPC_CH0 or DMA_CSAC */
  896 + if (s->ch[ch].omap_3_1_compatible_disable)
  897 + *value = s->ch[ch].active_set.src & 0xffff; /* CSAC */
  898 + else
  899 + *value = s->ch[ch].cpc;
  900 + break;
  901 +
  902 + case 0x1a: /* DMA_CDAC */
  903 + *value = s->ch[ch].active_set.dest & 0xffff; /* CDAC */
  904 + break;
  905 +
  906 + case 0x1c: /* DMA_CDEI */
  907 + *value = s->ch[ch].element_index[1];
  908 + break;
  909 +
  910 + case 0x1e: /* DMA_CDFI */
  911 + *value = s->ch[ch].frame_index[1];
  912 + break;
  913 +
  914 + case 0x20: /* DMA_COLOR_L */
  915 + *value = s->ch[ch].color & 0xffff;
  916 + break;
  917 +
  918 + case 0x22: /* DMA_COLOR_U */
  919 + *value = s->ch[ch].color >> 16;
754 920 break;
755 921  
756   - case 0x18: /* SYS_DMA_CPC_CH0 */
757   - *value = s->ch[ch].cpc;
  922 + case 0x24: /* DMA_CCR2 */
  923 + *value = (s->ch[ch].bs << 2) |
  924 + (s->ch[ch].transparent_copy << 1) |
  925 + s->ch[ch].constant_fill;
  926 + break;
  927 +
  928 + case 0x28: /* DMA_CLNK_CTRL */
  929 + *value = (s->ch[ch].link_enabled << 15) |
  930 + (s->ch[ch].link_next_ch & 0xf);
  931 + break;
  932 +
  933 + case 0x2a: /* DMA_LCH_CTRL */
  934 + *value = (s->ch[ch].interleave_disabled << 15) |
  935 + s->ch[ch].type;
758 936 break;
759 937  
760 938 default:
... ... @@ -764,7 +942,8 @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s,
764 942 }
765 943  
766 944 static int omap_dma_ch_reg_write(struct omap_dma_s *s,
767   - int ch, int reg, uint16_t value) {
  945 + int ch, int reg, uint16_t value)
  946 +{
768 947 switch (reg) {
769 948 case 0x00: /* SYS_DMA_CSDP_CH0 */
770 949 s->ch[ch].burst[1] = (value & 0xc000) >> 14;
... ... @@ -788,30 +967,26 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
788 967 s->ch[ch].mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
789 968 s->ch[ch].mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
790 969 s->ch[ch].end_prog = (value & 0x0800) >> 11;
  970 + if (s->model > omap_dma_3_1)
  971 + s->ch[ch].omap_3_1_compatible_disable = (value >> 10) & 0x1;
791 972 s->ch[ch].repeat = (value & 0x0200) >> 9;
792 973 s->ch[ch].auto_init = (value & 0x0100) >> 8;
793 974 s->ch[ch].priority = (value & 0x0040) >> 6;
794 975 s->ch[ch].fs = (value & 0x0020) >> 5;
795 976 s->ch[ch].sync = value & 0x001f;
796   - if (value & 0x0080) {
797   - if (s->ch[ch].running) {
798   - if (!s->ch[ch].signalled &&
799   - s->ch[ch].auto_init && s->ch[ch].end_prog)
800   - omap_dma_channel_load(s, ch);
801   - } else {
802   - s->ch[ch].running = 1;
803   - omap_dma_channel_load(s, ch);
804   - }
805   - if (!s->ch[ch].sync || (s->drq & (1 << s->ch[ch].sync)))
806   - omap_dma_request_run(s, ch, 0);
807   - } else {
808   - s->ch[ch].running = 0;
809   - omap_dma_request_stop(s, ch);
810   - }
  977 +
  978 + if (value & 0x0080)
  979 + omap_dma_enable_channel(s, ch);
  980 + else
  981 + omap_dma_disable_channel(s, ch);
  982 +
  983 + if (s->ch[ch].end_prog)
  984 + omap_dma_channel_end_prog(s, ch);
  985 +
811 986 break;
812 987  
813 988 case 0x04: /* SYS_DMA_CICR_CH0 */
814   - s->ch[ch].interrupts = value & 0x003f;
  989 + s->ch[ch].interrupts = value;
815 990 break;
816 991  
817 992 case 0x06: /* SYS_DMA_CSR_CH0 */
... ... @@ -838,97 +1013,317 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
838 1013 break;
839 1014  
840 1015 case 0x10: /* SYS_DMA_CEN_CH0 */
841   - s->ch[ch].elements = value & 0xffff;
  1016 + s->ch[ch].elements = value;
842 1017 break;
843 1018  
844 1019 case 0x12: /* SYS_DMA_CFN_CH0 */
845   - s->ch[ch].frames = value & 0xffff;
  1020 + s->ch[ch].frames = value;
846 1021 break;
847 1022  
848 1023 case 0x14: /* SYS_DMA_CFI_CH0 */
849   - s->ch[ch].frame_index = value & 0xffff;
  1024 + s->ch[ch].frame_index[0] = (int16_t) value;
850 1025 break;
851 1026  
852 1027 case 0x16: /* SYS_DMA_CEI_CH0 */
853   - s->ch[ch].element_index = value & 0xffff;
  1028 + s->ch[ch].element_index[0] = (int16_t) value;
854 1029 break;
855 1030  
856   - case 0x18: /* SYS_DMA_CPC_CH0 */
857   - return 1;
  1031 + case 0x18: /* SYS_DMA_CPC_CH0 or DMA_CSAC */
  1032 + OMAP_RO_REG((target_phys_addr_t) reg);
  1033 + break;
  1034 +
  1035 + case 0x1c: /* DMA_CDEI */
  1036 + s->ch[ch].element_index[1] = (int16_t) value;
  1037 + break;
  1038 +
  1039 + case 0x1e: /* DMA_CDFI */
  1040 + s->ch[ch].frame_index[1] = (int16_t) value;
  1041 + break;
  1042 +
  1043 + case 0x20: /* DMA_COLOR_L */
  1044 + s->ch[ch].color &= 0xffff0000;
  1045 + s->ch[ch].color |= value;
  1046 + break;
  1047 +
  1048 + case 0x22: /* DMA_COLOR_U */
  1049 + s->ch[ch].color &= 0xffff;
  1050 + s->ch[ch].color |= value << 16;
  1051 + break;
  1052 +
  1053 + case 0x24: /* DMA_CCR2 */
  1054 + s->ch[ch].bs = (value >> 2) & 0x1;
  1055 + s->ch[ch].transparent_copy = (value >> 1) & 0x1;
  1056 + s->ch[ch].constant_fill = value & 0x1;
  1057 + break;
  1058 +
  1059 + case 0x28: /* DMA_CLNK_CTRL */
  1060 + s->ch[ch].link_enabled = (value >> 15) & 0x1;
  1061 + if (value & (1 << 14)) { /* Stop_Lnk */
  1062 + s->ch[ch].link_enabled = 0;
  1063 + omap_dma_disable_channel(s, ch);
  1064 + }
  1065 + s->ch[ch].link_next_ch = value & 0x1f;
  1066 + break;
  1067 +
  1068 + case 0x2a: /* DMA_LCH_CTRL */
  1069 + s->ch[ch].interleave_disabled = (value >> 15) & 0x1;
  1070 + s->ch[ch].type = value & 0xf;
  1071 + break;
858 1072  
859 1073 default:
860   - OMAP_BAD_REG((target_phys_addr_t) reg);
  1074 + return 1;
861 1075 }
862 1076 return 0;
863 1077 }
864 1078  
865   -static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
  1079 +static int omap_dma_3_2_lcd_write(struct omap_dma_s *s, int offset,
  1080 + uint16_t value)
866 1081 {
867   - struct omap_dma_s *s = (struct omap_dma_s *) opaque;
868   - int i, reg, ch, offset = addr - s->base;
869   - uint16_t ret;
870   -
871 1082 switch (offset) {
872   - case 0x000 ... 0x2fe:
873   - reg = offset & 0x3f;
874   - ch = (offset >> 6) & 0x0f;
875   - if (omap_dma_ch_reg_read(s, ch, reg, &ret))
876   - break;
877   - return ret;
  1083 + case 0xbc0: /* DMA_LCD_CSDP */
  1084 + s->lcd_ch.brust_f2 = (value >> 14) & 0x3;
  1085 + s->lcd_ch.pack_f2 = (value >> 13) & 0x1;
  1086 + s->lcd_ch.data_type_f2 = (1 << ((value >> 11) & 0x3));
  1087 + s->lcd_ch.brust_f1 = (value >> 7) & 0x3;
  1088 + s->lcd_ch.pack_f1 = (value >> 6) & 0x1;
  1089 + s->lcd_ch.data_type_f1 = (1 << ((value >> 0) & 0x3));
  1090 + break;
878 1091  
879   - case 0x300: /* SYS_DMA_LCD_CTRL */
880   - i = s->lcd_ch.condition;
  1092 + case 0xbc2: /* DMA_LCD_CCR */
  1093 + s->lcd_ch.mode_f2 = (value >> 14) & 0x3;
  1094 + s->lcd_ch.mode_f1 = (value >> 12) & 0x3;
  1095 + s->lcd_ch.end_prog = (value >> 11) & 0x1;
  1096 + s->lcd_ch.omap_3_1_compatible_disable = (value >> 10) & 0x1;
  1097 + s->lcd_ch.repeat = (value >> 9) & 0x1;
  1098 + s->lcd_ch.auto_init = (value >> 8) & 0x1;
  1099 + s->lcd_ch.running = (value >> 7) & 0x1;
  1100 + s->lcd_ch.priority = (value >> 6) & 0x1;
  1101 + s->lcd_ch.bs = (value >> 4) & 0x1;
  1102 + break;
  1103 +
  1104 + case 0xbc4: /* DMA_LCD_CTRL */
  1105 + s->lcd_ch.dst = (value >> 8) & 0x1;
  1106 + s->lcd_ch.src = ((value >> 6) & 0x3) << 1;
881 1107 s->lcd_ch.condition = 0;
882   - qemu_irq_lower(s->lcd_ch.irq);
883   - return ((s->lcd_ch.src == imif) << 6) | (i << 3) |
884   - (s->lcd_ch.interrupts << 1) | s->lcd_ch.dual;
  1108 + /* Assume no bus errors and thus no BUS_ERROR irq bits. */
  1109 + s->lcd_ch.interrupts = (value >> 1) & 1;
  1110 + s->lcd_ch.dual = value & 1;
  1111 + break;
885 1112  
886   - case 0x302: /* SYS_DMA_LCD_TOP_F1_L */
887   - return s->lcd_ch.src_f1_top & 0xffff;
  1113 + case 0xbc8: /* TOP_B1_L */
  1114 + s->lcd_ch.src_f1_top &= 0xffff0000;
  1115 + s->lcd_ch.src_f1_top |= 0x0000ffff & value;
  1116 + break;
888 1117  
889   - case 0x304: /* SYS_DMA_LCD_TOP_F1_U */
890   - return s->lcd_ch.src_f1_top >> 16;
  1118 + case 0xbca: /* TOP_B1_U */
  1119 + s->lcd_ch.src_f1_top &= 0x0000ffff;
  1120 + s->lcd_ch.src_f1_top |= value << 16;
  1121 + break;
891 1122  
892   - case 0x306: /* SYS_DMA_LCD_BOT_F1_L */
893   - return s->lcd_ch.src_f1_bottom & 0xffff;
  1123 + case 0xbcc: /* BOT_B1_L */
  1124 + s->lcd_ch.src_f1_bottom &= 0xffff0000;
  1125 + s->lcd_ch.src_f1_bottom |= 0x0000ffff & value;
  1126 + break;
894 1127  
895   - case 0x308: /* SYS_DMA_LCD_BOT_F1_U */
896   - return s->lcd_ch.src_f1_bottom >> 16;
  1128 + case 0xbce: /* BOT_B1_U */
  1129 + s->lcd_ch.src_f1_bottom &= 0x0000ffff;
  1130 + s->lcd_ch.src_f1_bottom |= (uint32_t) value << 16;
  1131 + break;
897 1132  
898   - case 0x30a: /* SYS_DMA_LCD_TOP_F2_L */
899   - return s->lcd_ch.src_f2_top & 0xffff;
  1133 + case 0xbd0: /* TOP_B2_L */
  1134 + s->lcd_ch.src_f2_top &= 0xffff0000;
  1135 + s->lcd_ch.src_f2_top |= 0x0000ffff & value;
  1136 + break;
900 1137  
901   - case 0x30c: /* SYS_DMA_LCD_TOP_F2_U */
902   - return s->lcd_ch.src_f2_top >> 16;
  1138 + case 0xbd2: /* TOP_B2_U */
  1139 + s->lcd_ch.src_f2_top &= 0x0000ffff;
  1140 + s->lcd_ch.src_f2_top |= (uint32_t) value << 16;
  1141 + break;
903 1142  
904   - case 0x30e: /* SYS_DMA_LCD_BOT_F2_L */
905   - return s->lcd_ch.src_f2_bottom & 0xffff;
  1143 + case 0xbd4: /* BOT_B2_L */
  1144 + s->lcd_ch.src_f2_bottom &= 0xffff0000;
  1145 + s->lcd_ch.src_f2_bottom |= 0x0000ffff & value;
  1146 + break;
906 1147  
907   - case 0x310: /* SYS_DMA_LCD_BOT_F2_U */
908   - return s->lcd_ch.src_f2_bottom >> 16;
  1148 + case 0xbd6: /* BOT_B2_U */
  1149 + s->lcd_ch.src_f2_bottom &= 0x0000ffff;
  1150 + s->lcd_ch.src_f2_bottom |= (uint32_t) value << 16;
  1151 + break;
909 1152  
910   - case 0x400: /* SYS_DMA_GCR */
911   - return s->gcr;
912   - }
  1153 + case 0xbd8: /* DMA_LCD_SRC_EI_B1 */
  1154 + s->lcd_ch.element_index_f1 = value;
  1155 + break;
913 1156  
914   - OMAP_BAD_REG(addr);
  1157 + case 0xbda: /* DMA_LCD_SRC_FI_B1_L */
  1158 + s->lcd_ch.frame_index_f1 &= 0xffff0000;
  1159 + s->lcd_ch.frame_index_f1 |= 0x0000ffff & value;
  1160 + break;
  1161 +
  1162 + case 0xbf4: /* DMA_LCD_SRC_FI_B1_U */
  1163 + s->lcd_ch.frame_index_f1 &= 0x0000ffff;
  1164 + s->lcd_ch.frame_index_f1 |= (uint32_t) value << 16;
  1165 + break;
  1166 +
  1167 + case 0xbdc: /* DMA_LCD_SRC_EI_B2 */
  1168 + s->lcd_ch.element_index_f2 = value;
  1169 + break;
  1170 +
  1171 + case 0xbde: /* DMA_LCD_SRC_FI_B2_L */
  1172 + s->lcd_ch.frame_index_f2 &= 0xffff0000;
  1173 + s->lcd_ch.frame_index_f2 |= 0x0000ffff & value;
  1174 + break;
  1175 +
  1176 + case 0xbf6: /* DMA_LCD_SRC_FI_B2_U */
  1177 + s->lcd_ch.frame_index_f2 &= 0x0000ffff;
  1178 + s->lcd_ch.frame_index_f2 |= (uint32_t) value << 16;
  1179 + break;
  1180 +
  1181 + case 0xbe0: /* DMA_LCD_SRC_EN_B1 */
  1182 + s->lcd_ch.elements_f1 = value;
  1183 + break;
  1184 +
  1185 + case 0xbe4: /* DMA_LCD_SRC_FN_B1 */
  1186 + s->lcd_ch.frames_f1 = value;
  1187 + break;
  1188 +
  1189 + case 0xbe2: /* DMA_LCD_SRC_EN_B2 */
  1190 + s->lcd_ch.elements_f2 = value;
  1191 + break;
  1192 +
  1193 + case 0xbe6: /* DMA_LCD_SRC_FN_B2 */
  1194 + s->lcd_ch.frames_f2 = value;
  1195 + break;
  1196 +
  1197 + case 0xbea: /* DMA_LCD_LCH_CTRL */
  1198 + s->lcd_ch.lch_type = value & 0xf;
  1199 + break;
  1200 +
  1201 + default:
  1202 + return 1;
  1203 + }
915 1204 return 0;
916 1205 }
917 1206  
918   -static void omap_dma_write(void *opaque, target_phys_addr_t addr,
919   - uint32_t value)
  1207 +static int omap_dma_3_2_lcd_read(struct omap_dma_s *s, int offset,
  1208 + uint16_t *ret)
920 1209 {
921   - struct omap_dma_s *s = (struct omap_dma_s *) opaque;
922   - int reg, ch, offset = addr - s->base;
923   -
924 1210 switch (offset) {
925   - case 0x000 ... 0x2fe:
926   - reg = offset & 0x3f;
927   - ch = (offset >> 6) & 0x0f;
928   - if (omap_dma_ch_reg_write(s, ch, reg, value))
929   - OMAP_RO_REG(addr);
  1211 + case 0xbc0: /* DMA_LCD_CSDP */
  1212 + *ret = (s->lcd_ch.brust_f2 << 14) |
  1213 + (s->lcd_ch.pack_f2 << 13) |
  1214 + ((s->lcd_ch.data_type_f2 >> 1) << 11) |
  1215 + (s->lcd_ch.brust_f1 << 7) |
  1216 + (s->lcd_ch.pack_f1 << 6) |
  1217 + ((s->lcd_ch.data_type_f1 >> 1) << 0);
  1218 + break;
  1219 +
  1220 + case 0xbc2: /* DMA_LCD_CCR */
  1221 + *ret = (s->lcd_ch.mode_f2 << 14) |
  1222 + (s->lcd_ch.mode_f1 << 12) |
  1223 + (s->lcd_ch.end_prog << 11) |
  1224 + (s->lcd_ch.omap_3_1_compatible_disable << 10) |
  1225 + (s->lcd_ch.repeat << 9) |
  1226 + (s->lcd_ch.auto_init << 8) |
  1227 + (s->lcd_ch.running << 7) |
  1228 + (s->lcd_ch.priority << 6) |
  1229 + (s->lcd_ch.bs << 4);
  1230 + break;
  1231 +
  1232 + case 0xbc4: /* DMA_LCD_CTRL */
  1233 + qemu_irq_lower(s->lcd_ch.irq);
  1234 + *ret = (s->lcd_ch.dst << 8) |
  1235 + ((s->lcd_ch.src & 0x6) << 5) |
  1236 + (s->lcd_ch.condition << 3) |
  1237 + (s->lcd_ch.interrupts << 1) |
  1238 + s->lcd_ch.dual;
  1239 + break;
  1240 +
  1241 + case 0xbc8: /* TOP_B1_L */
  1242 + *ret = s->lcd_ch.src_f1_top & 0xffff;
  1243 + break;
  1244 +
  1245 + case 0xbca: /* TOP_B1_U */
  1246 + *ret = s->lcd_ch.src_f1_top >> 16;
  1247 + break;
  1248 +
  1249 + case 0xbcc: /* BOT_B1_L */
  1250 + *ret = s->lcd_ch.src_f1_bottom & 0xffff;
  1251 + break;
  1252 +
  1253 + case 0xbce: /* BOT_B1_U */
  1254 + *ret = s->lcd_ch.src_f1_bottom >> 16;
  1255 + break;
  1256 +
  1257 + case 0xbd0: /* TOP_B2_L */
  1258 + *ret = s->lcd_ch.src_f2_top & 0xffff;
  1259 + break;
  1260 +
  1261 + case 0xbd2: /* TOP_B2_U */
  1262 + *ret = s->lcd_ch.src_f2_top >> 16;
  1263 + break;
  1264 +
  1265 + case 0xbd4: /* BOT_B2_L */
  1266 + *ret = s->lcd_ch.src_f2_bottom & 0xffff;
930 1267 break;
931 1268  
  1269 + case 0xbd6: /* BOT_B2_U */
  1270 + *ret = s->lcd_ch.src_f2_bottom >> 16;
  1271 + break;
  1272 +
  1273 + case 0xbd8: /* DMA_LCD_SRC_EI_B1 */
  1274 + *ret = s->lcd_ch.element_index_f1;
  1275 + break;
  1276 +
  1277 + case 0xbda: /* DMA_LCD_SRC_FI_B1_L */
  1278 + *ret = s->lcd_ch.frame_index_f1 & 0xffff;
  1279 + break;
  1280 +
  1281 + case 0xbf4: /* DMA_LCD_SRC_FI_B1_U */
  1282 + *ret = s->lcd_ch.frame_index_f1 >> 16;
  1283 + break;
  1284 +
  1285 + case 0xbdc: /* DMA_LCD_SRC_EI_B2 */
  1286 + *ret = s->lcd_ch.element_index_f2;
  1287 + break;
  1288 +
  1289 + case 0xbde: /* DMA_LCD_SRC_FI_B2_L */
  1290 + *ret = s->lcd_ch.frame_index_f2 & 0xffff;
  1291 + break;
  1292 +
  1293 + case 0xbf6: /* DMA_LCD_SRC_FI_B2_U */
  1294 + *ret = s->lcd_ch.frame_index_f2 >> 16;
  1295 + break;
  1296 +
  1297 + case 0xbe0: /* DMA_LCD_SRC_EN_B1 */
  1298 + *ret = s->lcd_ch.elements_f1;
  1299 + break;
  1300 +
  1301 + case 0xbe4: /* DMA_LCD_SRC_FN_B1 */
  1302 + *ret = s->lcd_ch.frames_f1;
  1303 + break;
  1304 +
  1305 + case 0xbe2: /* DMA_LCD_SRC_EN_B2 */
  1306 + *ret = s->lcd_ch.elements_f2;
  1307 + break;
  1308 +
  1309 + case 0xbe6: /* DMA_LCD_SRC_FN_B2 */
  1310 + *ret = s->lcd_ch.frames_f2;
  1311 + break;
  1312 +
  1313 + case 0xbea: /* DMA_LCD_LCH_CTRL */
  1314 + *ret = s->lcd_ch.lch_type;
  1315 + break;
  1316 +
  1317 + default:
  1318 + return 1;
  1319 + }
  1320 + return 0;
  1321 +}
  1322 +
  1323 +static int omap_dma_3_1_lcd_write(struct omap_dma_s *s, int offset,
  1324 + uint16_t value)
  1325 +{
  1326 + switch (offset) {
932 1327 case 0x300: /* SYS_DMA_LCD_CTRL */
933 1328 s->lcd_ch.src = (value & 0x40) ? imif : emiff;
934 1329 s->lcd_ch.condition = 0;
... ... @@ -977,13 +1372,257 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr,
977 1372 s->lcd_ch.src_f2_bottom |= value << 16;
978 1373 break;
979 1374  
  1375 + default:
  1376 + return 1;
  1377 + }
  1378 + return 0;
  1379 +}
  1380 +
  1381 +static int omap_dma_3_1_lcd_read(struct omap_dma_s *s, int offset,
  1382 + uint16_t *ret)
  1383 +{
  1384 + int i;
  1385 +
  1386 + switch (offset) {
  1387 + case 0x300: /* SYS_DMA_LCD_CTRL */
  1388 + i = s->lcd_ch.condition;
  1389 + s->lcd_ch.condition = 0;
  1390 + qemu_irq_lower(s->lcd_ch.irq);
  1391 + *ret = ((s->lcd_ch.src == imif) << 6) | (i << 3) |
  1392 + (s->lcd_ch.interrupts << 1) | s->lcd_ch.dual;
  1393 + break;
  1394 +
  1395 + case 0x302: /* SYS_DMA_LCD_TOP_F1_L */
  1396 + *ret = s->lcd_ch.src_f1_top & 0xffff;
  1397 + break;
  1398 +
  1399 + case 0x304: /* SYS_DMA_LCD_TOP_F1_U */
  1400 + *ret = s->lcd_ch.src_f1_top >> 16;
  1401 + break;
  1402 +
  1403 + case 0x306: /* SYS_DMA_LCD_BOT_F1_L */
  1404 + *ret = s->lcd_ch.src_f1_bottom & 0xffff;
  1405 + break;
  1406 +
  1407 + case 0x308: /* SYS_DMA_LCD_BOT_F1_U */
  1408 + *ret = s->lcd_ch.src_f1_bottom >> 16;
  1409 + break;
  1410 +
  1411 + case 0x30a: /* SYS_DMA_LCD_TOP_F2_L */
  1412 + *ret = s->lcd_ch.src_f2_top & 0xffff;
  1413 + break;
  1414 +
  1415 + case 0x30c: /* SYS_DMA_LCD_TOP_F2_U */
  1416 + *ret = s->lcd_ch.src_f2_top >> 16;
  1417 + break;
  1418 +
  1419 + case 0x30e: /* SYS_DMA_LCD_BOT_F2_L */
  1420 + *ret = s->lcd_ch.src_f2_bottom & 0xffff;
  1421 + break;
  1422 +
  1423 + case 0x310: /* SYS_DMA_LCD_BOT_F2_U */
  1424 + *ret = s->lcd_ch.src_f2_bottom >> 16;
  1425 + break;
  1426 +
  1427 + default:
  1428 + return 1;
  1429 + }
  1430 + return 0;
  1431 +}
  1432 +
  1433 +static int omap_dma_sys_write(struct omap_dma_s *s, int offset, uint16_t value)
  1434 +{
  1435 + switch (offset) {
980 1436 case 0x400: /* SYS_DMA_GCR */
981   - s->gcr = value & 0x000c;
  1437 + s->gcr = value;
  1438 + break;
  1439 +
  1440 + case 0x404: /* DMA_GSCR */
  1441 + if (value & 0x8)
  1442 + omap_dma_disable_3_1_mapping(s);
  1443 + else
  1444 + omap_dma_enable_3_1_mapping(s);
  1445 + break;
  1446 +
  1447 + case 0x408: /* DMA_GRST */
  1448 + if (value & 0x1)
  1449 + omap_dma_reset(s);
982 1450 break;
983 1451  
984 1452 default:
985   - OMAP_BAD_REG(addr);
  1453 + return 1;
986 1454 }
  1455 + return 0;
  1456 +}
  1457 +
  1458 +static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
  1459 + uint16_t *ret)
  1460 +{
  1461 + switch (offset) {
  1462 + case 0x400: /* SYS_DMA_GCR */
  1463 + *ret = s->gcr;
  1464 + break;
  1465 +
  1466 + case 0x404: /* DMA_GSCR */
  1467 + *ret = s->omap_3_1_mapping_disabled << 3;
  1468 + break;
  1469 +
  1470 + case 0x408: /* DMA_GRST */
  1471 + *ret = 0;
  1472 + break;
  1473 +
  1474 + case 0x442: /* DMA_HW_ID */
  1475 + case 0x444: /* DMA_PCh2_ID */
  1476 + case 0x446: /* DMA_PCh0_ID */
  1477 + case 0x448: /* DMA_PCh1_ID */
  1478 + case 0x44a: /* DMA_PChG_ID */
  1479 + case 0x44c: /* DMA_PChD_ID */
  1480 + *ret = 1;
  1481 + break;
  1482 +
  1483 + case 0x44e: /* DMA_CAPS_0_U */
  1484 + *ret = (1 << 3) | /* Constant Fill Capacity */
  1485 + (1 << 2); /* Transparent BLT Capacity */
  1486 + break;
  1487 +
  1488 + case 0x450: /* DMA_CAPS_0_L */
  1489 + case 0x452: /* DMA_CAPS_1_U */
  1490 + *ret = 0;
  1491 + break;
  1492 +
  1493 + case 0x454: /* DMA_CAPS_1_L */
  1494 + *ret = (1 << 1); /* 1-bit palletized capability */
  1495 + break;
  1496 +
  1497 + case 0x456: /* DMA_CAPS_2 */
  1498 + *ret = (1 << 8) | /* SSDIC */
  1499 + (1 << 7) | /* DDIAC */
  1500 + (1 << 6) | /* DSIAC */
  1501 + (1 << 5) | /* DPIAC */
  1502 + (1 << 4) | /* DCAC */
  1503 + (1 << 3) | /* SDIAC */
  1504 + (1 << 2) | /* SSIAC */
  1505 + (1 << 1) | /* SPIAC */
  1506 + 1; /* SCAC */
  1507 + break;
  1508 +
  1509 + case 0x458: /* DMA_CAPS_3 */
  1510 + *ret = (1 << 5) | /* CCC */
  1511 + (1 << 4) | /* IC */
  1512 + (1 << 3) | /* ARC */
  1513 + (1 << 2) | /* AEC */
  1514 + (1 << 1) | /* FSC */
  1515 + 1; /* ESC */
  1516 + break;
  1517 +
  1518 + case 0x45a: /* DMA_CAPS_4 */
  1519 + *ret = (1 << 6) | /* SSC */
  1520 + (1 << 5) | /* BIC */
  1521 + (1 << 4) | /* LFIC */
  1522 + (1 << 3) | /* FIC */
  1523 + (1 << 2) | /* HFIC */
  1524 + (1 << 1) | /* EDIC */
  1525 + 1; /* TOIC */
  1526 + break;
  1527 +
  1528 + case 0x460: /* DMA_PCh2_SR */
  1529 + case 0x480: /* DMA_PCh0_SR */
  1530 + case 0x482: /* DMA_PCh1_SR */
  1531 + case 0x4c0: /* DMA_PChD_SR_0 */
  1532 + printf("%s: Physical Channel Status Registers not implemented.\n",
  1533 + __FUNCTION__);
  1534 + *ret = 0xff;
  1535 + break;
  1536 +
  1537 + default:
  1538 + return 1;
  1539 + }
  1540 + return 0;
  1541 +}
  1542 +
  1543 +static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
  1544 +{
  1545 + struct omap_dma_s *s = (struct omap_dma_s *) opaque;
  1546 + int reg, ch, offset = addr - s->base;
  1547 + uint16_t ret;
  1548 +
  1549 + switch (offset) {
  1550 + case 0x300 ... 0x3fe:
  1551 + if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
  1552 + if (omap_dma_3_1_lcd_read(s, offset, &ret))
  1553 + break;
  1554 + return ret;
  1555 + }
  1556 + /* Fall through. */
  1557 + case 0x000 ... 0x2fe:
  1558 + reg = offset & 0x3f;
  1559 + ch = (offset >> 6) & 0x0f;
  1560 + if (omap_dma_ch_reg_read(s, ch, reg, &ret))
  1561 + break;
  1562 + return ret;
  1563 +
  1564 + case 0x404 ... 0x4fe:
  1565 + if (s->model == omap_dma_3_1)
  1566 + break;
  1567 + /* Fall through. */
  1568 + case 0x400:
  1569 + if (omap_dma_sys_read(s, offset, &ret))
  1570 + break;
  1571 + return ret;
  1572 +
  1573 + case 0xb00 ... 0xbfe:
  1574 + if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) {
  1575 + if (omap_dma_3_2_lcd_read(s, offset, &ret))
  1576 + break;
  1577 + return ret;
  1578 + }
  1579 + break;
  1580 + }
  1581 +
  1582 + OMAP_BAD_REG(addr);
  1583 + return 0;
  1584 +}
  1585 +
  1586 +static void omap_dma_write(void *opaque, target_phys_addr_t addr,
  1587 + uint32_t value)
  1588 +{
  1589 + struct omap_dma_s *s = (struct omap_dma_s *) opaque;
  1590 + int reg, ch, offset = addr - s->base;
  1591 +
  1592 + switch (offset) {
  1593 + case 0x300 ... 0x3fe:
  1594 + if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
  1595 + if (omap_dma_3_1_lcd_write(s, offset, value))
  1596 + break;
  1597 + return;
  1598 + }
  1599 + /* Fall through. */
  1600 + case 0x000 ... 0x2fe:
  1601 + reg = offset & 0x3f;
  1602 + ch = (offset >> 6) & 0x0f;
  1603 + if (omap_dma_ch_reg_write(s, ch, reg, value))
  1604 + break;
  1605 + return;
  1606 +
  1607 + case 0x404 ... 0x4fe:
  1608 + if (s->model == omap_dma_3_1)
  1609 + break;
  1610 + case 0x400:
  1611 + /* Fall through. */
  1612 + if (omap_dma_sys_write(s, offset, value))
  1613 + break;
  1614 + return;
  1615 +
  1616 + case 0xb00 ... 0xbfe:
  1617 + if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) {
  1618 + if (omap_dma_3_2_lcd_write(s, offset, value))
  1619 + break;
  1620 + return;
  1621 + }
  1622 + break;
  1623 + }
  1624 +
  1625 + OMAP_BAD_REG(addr);
987 1626 }
988 1627  
989 1628 static CPUReadMemoryFunc *omap_dma_readfn[] = {
... ... @@ -1005,7 +1644,7 @@ static void omap_dma_request(void *opaque, int drq, int req)
1005 1644 if (req) {
1006 1645 if (~s->drq & (1 << drq)) {
1007 1646 s->drq |= 1 << drq;
1008   - omap_dma_request_run(s, 0, drq);
  1647 + omap_dma_process_request(s, drq);
1009 1648 }
1010 1649 } else
1011 1650 s->drq &= ~(1 << drq);
... ... @@ -1026,36 +1665,27 @@ static void omap_dma_clk_update(void *opaque, int line, int on)
1026 1665 }
1027 1666 }
1028 1667  
1029   -static void omap_dma_reset(struct omap_dma_s *s)
1030   -{
1031   - int i;
1032   -
1033   - qemu_del_timer(s->tm);
1034   - s->gcr = 0x0004;
1035   - s->drq = 0x00000000;
1036   - s->run_count = 0;
1037   - s->lcd_ch.src = emiff;
1038   - s->lcd_ch.condition = 0;
1039   - s->lcd_ch.interrupts = 0;
1040   - s->lcd_ch.dual = 0;
1041   - memset(s->ch, 0, sizeof(s->ch));
1042   - for (i = 0; i < s->chans; i ++)
1043   - s->ch[i].interrupts = 0x0003;
1044   -}
1045   -
1046   -struct omap_dma_s *omap_dma_init(target_phys_addr_t base,
1047   - qemu_irq pic[], struct omap_mpu_state_s *mpu, omap_clk clk)
  1668 +struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
  1669 + qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
  1670 + enum omap_dma_model model)
1048 1671 {
1049   - int iomemtype;
  1672 + int iomemtype, num_irqs, memsize;
1050 1673 struct omap_dma_s *s = (struct omap_dma_s *)
1051 1674 qemu_mallocz(sizeof(struct omap_dma_s));
1052 1675  
1053   - s->ih = pic;
  1676 + if (model == omap_dma_3_1) {
  1677 + num_irqs = 6;
  1678 + memsize = 0x800;
  1679 + } else {
  1680 + num_irqs = 16;
  1681 + memsize = 0xc00;
  1682 + }
  1683 + memcpy(s->irqs, irqs, num_irqs * sizeof(qemu_irq));
1054 1684 s->base = base;
1055   - s->chans = 9;
  1685 + s->model = model;
1056 1686 s->mpu = mpu;
1057 1687 s->clk = clk;
1058   - s->lcd_ch.irq = pic[OMAP_INT_DMA_LCD];
  1688 + s->lcd_ch.irq = lcd_irq;
1059 1689 s->lcd_ch.mpu = mpu;
1060 1690 s->tm = qemu_new_timer(vm_clock, (QEMUTimerCB *) omap_dma_channel_run, s);
1061 1691 omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
... ... @@ -1065,7 +1695,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base,
1065 1695  
1066 1696 iomemtype = cpu_register_io_memory(0, omap_dma_readfn,
1067 1697 omap_dma_writefn, s);
1068   - cpu_register_physical_memory(s->base, 0x800, iomemtype);
  1698 + cpu_register_physical_memory(s->base, memsize, iomemtype);
1069 1699  
1070 1700 return s;
1071 1701 }
... ... @@ -4919,13 +5549,39 @@ static void omap_mpu_wakeup(void *opaque, int irq, int req)
4919 5549 cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
4920 5550 }
4921 5551  
  5552 +struct dma_irq_map {
  5553 + int ih;
  5554 + int intr;
  5555 +};
  5556 +
  5557 +static const struct dma_irq_map omap_dma_irq_map[] = {
  5558 + { 0, OMAP_INT_DMA_CH0_6 },
  5559 + { 0, OMAP_INT_DMA_CH1_7 },
  5560 + { 0, OMAP_INT_DMA_CH2_8 },
  5561 + { 0, OMAP_INT_DMA_CH3 },
  5562 + { 0, OMAP_INT_DMA_CH4 },
  5563 + { 0, OMAP_INT_DMA_CH5 },
  5564 + { 1, OMAP_INT_1610_DMA_CH6 },
  5565 + { 1, OMAP_INT_1610_DMA_CH7 },
  5566 + { 1, OMAP_INT_1610_DMA_CH8 },
  5567 + { 1, OMAP_INT_1610_DMA_CH9 },
  5568 + { 1, OMAP_INT_1610_DMA_CH10 },
  5569 + { 1, OMAP_INT_1610_DMA_CH11 },
  5570 + { 1, OMAP_INT_1610_DMA_CH12 },
  5571 + { 1, OMAP_INT_1610_DMA_CH13 },
  5572 + { 1, OMAP_INT_1610_DMA_CH14 },
  5573 + { 1, OMAP_INT_1610_DMA_CH15 }
  5574 +};
  5575 +
4922 5576 struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
4923 5577 DisplayState *ds, const char *core)
4924 5578 {
  5579 + int i;
4925 5580 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
4926 5581 qemu_mallocz(sizeof(struct omap_mpu_state_s));
4927 5582 ram_addr_t imif_base, emiff_base;
4928 5583 qemu_irq *cpu_irq;
  5584 + qemu_irq dma_irqs[6];
4929 5585 int sdindex;
4930 5586  
4931 5587 if (!core)
... ... @@ -4964,8 +5620,11 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
4964 5620 s->irq[0] = s->ih[0]->pins;
4965 5621 s->irq[1] = s->ih[1]->pins;
4966 5622  
4967   - s->dma = omap_dma_init(0xfffed800, s->irq[0], s,
4968   - omap_findclk(s, "dma_ck"));
  5623 + for (i = 0; i < 6; i ++)
  5624 + dma_irqs[i] = s->irq[omap_dma_irq_map[i].ih][omap_dma_irq_map[i].intr];
  5625 + s->dma = omap_dma_init(0xfffed800, dma_irqs, s->irq[0][OMAP_INT_DMA_LCD],
  5626 + s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
  5627 +
4969 5628 s->port[emiff ].addr_valid = omap_validate_emiff_addr;
4970 5629 s->port[emifs ].addr_valid = omap_validate_emifs_addr;
4971 5630 s->port[imif ].addr_valid = omap_validate_imif_addr;
... ...
hw/omap.h
... ... @@ -336,26 +336,68 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
336 336 # define OMAP_INT_243X_HS_USB_DMA 93
337 337 # define OMAP_INT_243X_CARKIT 94
338 338  
  339 +enum omap_dma_model {
  340 + omap_dma_3_1 = 0,
  341 + omap_dma_3_2
  342 +};
  343 +
339 344 struct omap_dma_s;
340   -struct omap_dma_s *omap_dma_init(target_phys_addr_t base,
341   - qemu_irq pic[], struct omap_mpu_state_s *mpu, omap_clk clk);
  345 +struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
  346 + qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
  347 + enum omap_dma_model model);
342 348  
343 349 enum omap_dma_port {
344 350 emiff = 0,
345 351 emifs,
346   - imif,
  352 + imif, /* omap16xx: ocp_t1 */
347 353 tipb,
348   - local,
  354 + local, /* omap16xx: ocp_t2 */
349 355 tipb_mpui,
350 356 omap_dma_port_last,
351 357 };
352 358  
  359 +typedef enum {
  360 + constant = 0,
  361 + post_incremented,
  362 + single_index,
  363 + double_index,
  364 +} omap_dma_addressing_t;
  365 +
353 366 struct omap_dma_lcd_channel_s {
354 367 enum omap_dma_port src;
355 368 target_phys_addr_t src_f1_top;
356 369 target_phys_addr_t src_f1_bottom;
357 370 target_phys_addr_t src_f2_top;
358 371 target_phys_addr_t src_f2_bottom;
  372 +
  373 + /* Used in OMAP DMA 3.2 gigacell */
  374 + unsigned char brust_f1;
  375 + unsigned char pack_f1;
  376 + unsigned char data_type_f1;
  377 + unsigned char brust_f2;
  378 + unsigned char pack_f2;
  379 + unsigned char data_type_f2;
  380 + unsigned char end_prog;
  381 + unsigned char repeat;
  382 + unsigned char auto_init;
  383 + unsigned char priority;
  384 + unsigned char fs;
  385 + unsigned char running;
  386 + unsigned char bs;
  387 + unsigned char omap_3_1_compatible_disable;
  388 + unsigned char dst;
  389 + unsigned char lch_type;
  390 + int16_t element_index_f1;
  391 + int16_t element_index_f2;
  392 + int32_t frame_index_f1;
  393 + int32_t frame_index_f2;
  394 + uint16_t elements_f1;
  395 + uint16_t frames_f1;
  396 + uint16_t elements_f2;
  397 + uint16_t frames_f2;
  398 + omap_dma_addressing_t mode_f1;
  399 + omap_dma_addressing_t mode_f2;
  400 +
359 401 /* Destination port is fixed. */
360 402 int interrupts;
361 403 int condition;
... ...