aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/dma/amba-pl08x.c141
-rw-r--r--include/linux/amba/pl08x.h2
2 files changed, 17 insertions, 126 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 6bba32e5ddb..be9a1c718f9 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -149,14 +149,6 @@ struct pl08x_driver_data {
149 * PL08X specific defines 149 * PL08X specific defines
150 */ 150 */
151 151
152/*
153 * Memory boundaries: the manual for PL08x says that the controller
154 * cannot read past a 1KiB boundary, so these defines are used to
155 * create transfer LLIs that do not cross such boundaries.
156 */
157#define PL08X_BOUNDARY_SHIFT (10) /* 1KB 0x400 */
158#define PL08X_BOUNDARY_SIZE (1 << PL08X_BOUNDARY_SHIFT)
159
160/* Size (bytes) of each LLI buffer allocated for one transfer */ 152/* Size (bytes) of each LLI buffer allocated for one transfer */
161# define PL08X_LLI_TSFR_SIZE 0x2000 153# define PL08X_LLI_TSFR_SIZE 0x2000
162 154
@@ -568,18 +560,6 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
568} 560}
569 561
570/* 562/*
571 * Return number of bytes to fill to boundary, or len.
572 * This calculation works for any value of addr.
573 */
574static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
575{
576 size_t boundary_len = PL08X_BOUNDARY_SIZE -
577 (addr & (PL08X_BOUNDARY_SIZE - 1));
578
579 return min(boundary_len, len);
580}
581
582/*
583 * This fills in the table of LLIs for the transfer descriptor 563 * This fills in the table of LLIs for the transfer descriptor
584 * Note that we assume we never have to change the burst sizes 564 * Note that we assume we never have to change the burst sizes
585 * Return 0 for error 565 * Return 0 for error
@@ -685,118 +665,30 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
685 * width left 665 * width left
686 */ 666 */
687 while (bd.remainder > (mbus->buswidth - 1)) { 667 while (bd.remainder > (mbus->buswidth - 1)) {
688 size_t lli_len, target_len, tsize, odd_bytes; 668 size_t lli_len, tsize;
689 669
690 /* 670 /*
691 * If enough left try to send max possible, 671 * If enough left try to send max possible,
692 * otherwise try to send the remainder 672 * otherwise try to send the remainder
693 */ 673 */
694 target_len = min(bd.remainder, max_bytes_per_lli); 674 lli_len = min(bd.remainder, max_bytes_per_lli);
695
696 /* 675 /*
697 * Set bus lengths for incrementing buses to the 676 * Check against minimum bus alignment: Calculate actual
698 * number of bytes which fill to next memory boundary, 677 * transfer size in relation to bus width and get a
699 * limiting on the target length calculated above. 678 * maximum remainder of the smallest bus width - 1
700 */ 679 */
701 if (cctl & PL080_CONTROL_SRC_INCR) 680 tsize = lli_len / min(mbus->buswidth, sbus->buswidth);
702 bd.srcbus.fill_bytes = 681 lli_len = tsize * min(mbus->buswidth, sbus->buswidth);
703 pl08x_pre_boundary(bd.srcbus.addr,
704 target_len);
705 else
706 bd.srcbus.fill_bytes = target_len;
707
708 if (cctl & PL080_CONTROL_DST_INCR)
709 bd.dstbus.fill_bytes =
710 pl08x_pre_boundary(bd.dstbus.addr,
711 target_len);
712 else
713 bd.dstbus.fill_bytes = target_len;
714
715 /* Find the nearest */
716 lli_len = min(bd.srcbus.fill_bytes,
717 bd.dstbus.fill_bytes);
718
719 BUG_ON(lli_len > bd.remainder);
720
721 if (lli_len <= 0) {
722 dev_err(&pl08x->adev->dev,
723 "%s lli_len is %zu, <= 0\n",
724 __func__, lli_len);
725 return 0;
726 }
727
728 if (lli_len == target_len) {
729 /*
730 * Can send what we wanted.
731 * Maintain alignment
732 */
733 lli_len = (lli_len/mbus->buswidth) *
734 mbus->buswidth;
735 odd_bytes = 0;
736 } else {
737 /*
738 * So now we know how many bytes to transfer
739 * to get to the nearest boundary. The next
740 * LLI will past the boundary. However, we
741 * may be working to a boundary on the slave
742 * bus. We need to ensure the master stays
743 * aligned, and that we are working in
744 * multiples of the bus widths.
745 */
746 odd_bytes = lli_len % mbus->buswidth;
747 lli_len -= odd_bytes;
748
749 }
750
751 if (lli_len) {
752 /*
753 * Check against minimum bus alignment:
754 * Calculate actual transfer size in relation
755 * to bus width an get a maximum remainder of
756 * the smallest bus width - 1
757 */
758 /* FIXME: use round_down()? */
759 tsize = lli_len / min(mbus->buswidth,
760 sbus->buswidth);
761 lli_len = tsize * min(mbus->buswidth,
762 sbus->buswidth);
763
764 if (target_len != lli_len) {
765 dev_vdbg(&pl08x->adev->dev,
766 "%s can't send what we want. Desired 0x%08zx, lli of 0x%08zx bytes in txd of 0x%08zx\n",
767 __func__, target_len, lli_len, txd->len);
768 }
769
770 cctl = pl08x_cctl_bits(cctl,
771 bd.srcbus.buswidth,
772 bd.dstbus.buswidth,
773 tsize);
774
775 dev_vdbg(&pl08x->adev->dev,
776 "%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n",
777 __func__, lli_len, bd.remainder);
778 pl08x_fill_lli_for_desc(&bd, num_llis++,
779 lli_len, cctl);
780 total_bytes += lli_len;
781 }
782 682
783 if (odd_bytes) { 683 dev_vdbg(&pl08x->adev->dev,
784 /* 684 "%s fill lli with single lli chunk of "
785 * Creep past the boundary, maintaining 685 "size 0x%08zx (remainder 0x%08zx)\n",
786 * master alignment 686 __func__, lli_len, bd.remainder);
787 */ 687
788 int j; 688 cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
789 for (j = 0; (j < mbus->buswidth) 689 bd.dstbus.buswidth, tsize);
790 && (bd.remainder); j++) { 690 pl08x_fill_lli_for_desc(&bd, num_llis++, lli_len, cctl);
791 cctl = pl08x_cctl_bits(cctl, 1, 1, 1); 691 total_bytes += lli_len;
792 dev_vdbg(&pl08x->adev->dev,
793 "%s align with boundary, single byte (remain 0x%08zx)\n",
794 __func__, bd.remainder);
795 pl08x_fill_lli_for_desc(&bd,
796 num_llis++, 1, cctl);
797 total_bytes++;
798 }
799 }
800 } 692 }
801 693
802 /* 694 /*
@@ -811,6 +703,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
811 total_bytes++; 703 total_bytes++;
812 } 704 }
813 } 705 }
706
814 if (total_bytes != txd->len) { 707 if (total_bytes != txd->len) {
815 dev_err(&pl08x->adev->dev, 708 dev_err(&pl08x->adev->dev,
816 "%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n", 709 "%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h
index cd8f629da58..ecd17f581e7 100644
--- a/include/linux/amba/pl08x.h
+++ b/include/linux/amba/pl08x.h
@@ -77,13 +77,11 @@ struct pl08x_channel_data {
77 * @addr: current address 77 * @addr: current address
78 * @maxwidth: the maximum width of a transfer on this bus 78 * @maxwidth: the maximum width of a transfer on this bus
79 * @buswidth: the width of this bus in bytes: 1, 2 or 4 79 * @buswidth: the width of this bus in bytes: 1, 2 or 4
80 * @fill_bytes: bytes required to fill to the next bus memory boundary
81 */ 80 */
82struct pl08x_bus_data { 81struct pl08x_bus_data {
83 dma_addr_t addr; 82 dma_addr_t addr;
84 u8 maxwidth; 83 u8 maxwidth;