diff options
author | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2016-11-29 09:23:42 -0500 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2016-11-29 22:24:04 -0500 |
commit | 201ac4861c1944ec3794364d6898b4ddfeb0faf8 (patch) | |
tree | e6a2fe1ecdbee7f38d2701b9bb257e7804d41070 | |
parent | 54cd255808761ecfd0e000eb78eb74dde8cd0c96 (diff) |
dmaengine: omap-dma: Support for slave devices with data port window
Based on the src/dst_port_window_size - if it is set - configure the DMA
channel to use double indexing in order to be able to loop within the
address window.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r-- | drivers/dma/omap-dma.c | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 15eb8024666b..ac68666cd3f4 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c | |||
@@ -166,6 +166,9 @@ enum { | |||
166 | CSDP_DST_BURST_16 = 1 << 14, | 166 | CSDP_DST_BURST_16 = 1 << 14, |
167 | CSDP_DST_BURST_32 = 2 << 14, | 167 | CSDP_DST_BURST_32 = 2 << 14, |
168 | CSDP_DST_BURST_64 = 3 << 14, | 168 | CSDP_DST_BURST_64 = 3 << 14, |
169 | CSDP_WRITE_NON_POSTED = 0 << 16, | ||
170 | CSDP_WRITE_POSTED = 1 << 16, | ||
171 | CSDP_WRITE_LAST_NON_POSTED = 2 << 16, | ||
169 | 172 | ||
170 | CICR_TOUT_IE = BIT(0), /* OMAP1 only */ | 173 | CICR_TOUT_IE = BIT(0), /* OMAP1 only */ |
171 | CICR_DROP_IE = BIT(1), | 174 | CICR_DROP_IE = BIT(1), |
@@ -881,15 +884,18 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( | |||
881 | unsigned i, es, en, frame_bytes; | 884 | unsigned i, es, en, frame_bytes; |
882 | bool ll_failed = false; | 885 | bool ll_failed = false; |
883 | u32 burst; | 886 | u32 burst; |
887 | u32 port_window, port_window_bytes; | ||
884 | 888 | ||
885 | if (dir == DMA_DEV_TO_MEM) { | 889 | if (dir == DMA_DEV_TO_MEM) { |
886 | dev_addr = c->cfg.src_addr; | 890 | dev_addr = c->cfg.src_addr; |
887 | dev_width = c->cfg.src_addr_width; | 891 | dev_width = c->cfg.src_addr_width; |
888 | burst = c->cfg.src_maxburst; | 892 | burst = c->cfg.src_maxburst; |
893 | port_window = c->cfg.src_port_window_size; | ||
889 | } else if (dir == DMA_MEM_TO_DEV) { | 894 | } else if (dir == DMA_MEM_TO_DEV) { |
890 | dev_addr = c->cfg.dst_addr; | 895 | dev_addr = c->cfg.dst_addr; |
891 | dev_width = c->cfg.dst_addr_width; | 896 | dev_width = c->cfg.dst_addr_width; |
892 | burst = c->cfg.dst_maxburst; | 897 | burst = c->cfg.dst_maxburst; |
898 | port_window = c->cfg.dst_port_window_size; | ||
893 | } else { | 899 | } else { |
894 | dev_err(chan->device->dev, "%s: bad direction?\n", __func__); | 900 | dev_err(chan->device->dev, "%s: bad direction?\n", __func__); |
895 | return NULL; | 901 | return NULL; |
@@ -910,6 +916,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( | |||
910 | return NULL; | 916 | return NULL; |
911 | } | 917 | } |
912 | 918 | ||
919 | /* When the port_window is used, one frame must cover the window */ | ||
920 | if (port_window) { | ||
921 | burst = port_window; | ||
922 | port_window_bytes = port_window * es_bytes[es]; | ||
923 | } | ||
924 | |||
913 | /* Now allocate and setup the descriptor. */ | 925 | /* Now allocate and setup the descriptor. */ |
914 | d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC); | 926 | d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC); |
915 | if (!d) | 927 | if (!d) |
@@ -921,11 +933,45 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( | |||
921 | 933 | ||
922 | d->ccr = c->ccr | CCR_SYNC_FRAME; | 934 | d->ccr = c->ccr | CCR_SYNC_FRAME; |
923 | if (dir == DMA_DEV_TO_MEM) { | 935 | if (dir == DMA_DEV_TO_MEM) { |
924 | d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; | ||
925 | d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED; | 936 | d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED; |
937 | |||
938 | d->ccr |= CCR_DST_AMODE_POSTINC; | ||
939 | if (port_window) { | ||
940 | d->ccr |= CCR_SRC_AMODE_DBLIDX; | ||
941 | d->ei = 1; | ||
942 | /* | ||
943 | * One frame covers the port_window and by configure | ||
944 | * the source frame index to be -1 * (port_window - 1) | ||
945 | * we instruct the sDMA that after a frame is processed | ||
946 | * it should move back to the start of the window. | ||
947 | */ | ||
948 | d->fi = -(port_window_bytes - 1); | ||
949 | |||
950 | if (port_window_bytes >= 64) | ||
951 | d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED; | ||
952 | else if (port_window_bytes >= 32) | ||
953 | d->csdp = CSDP_SRC_BURST_32 | CSDP_SRC_PACKED; | ||
954 | else if (port_window_bytes >= 16) | ||
955 | d->csdp = CSDP_SRC_BURST_16 | CSDP_SRC_PACKED; | ||
956 | } else { | ||
957 | d->ccr |= CCR_SRC_AMODE_CONSTANT; | ||
958 | } | ||
926 | } else { | 959 | } else { |
927 | d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC; | ||
928 | d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED; | 960 | d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED; |
961 | |||
962 | d->ccr |= CCR_SRC_AMODE_POSTINC; | ||
963 | if (port_window) { | ||
964 | d->ccr |= CCR_DST_AMODE_DBLIDX; | ||
965 | |||
966 | if (port_window_bytes >= 64) | ||
967 | d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED; | ||
968 | else if (port_window_bytes >= 32) | ||
969 | d->csdp = CSDP_DST_BURST_32 | CSDP_DST_PACKED; | ||
970 | else if (port_window_bytes >= 16) | ||
971 | d->csdp = CSDP_DST_BURST_16 | CSDP_DST_PACKED; | ||
972 | } else { | ||
973 | d->ccr |= CCR_DST_AMODE_CONSTANT; | ||
974 | } | ||
929 | } | 975 | } |
930 | 976 | ||
931 | d->cicr = CICR_DROP_IE | CICR_BLOCK_IE; | 977 | d->cicr = CICR_DROP_IE | CICR_BLOCK_IE; |
@@ -943,6 +989,9 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( | |||
943 | d->ccr |= CCR_TRIGGER_SRC; | 989 | d->ccr |= CCR_TRIGGER_SRC; |
944 | 990 | ||
945 | d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; | 991 | d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; |
992 | |||
993 | if (port_window) | ||
994 | d->csdp |= CSDP_WRITE_LAST_NON_POSTED; | ||
946 | } | 995 | } |
947 | if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) | 996 | if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) |
948 | d->clnk_ctrl = c->dma_ch; | 997 | d->clnk_ctrl = c->dma_ch; |
@@ -968,6 +1017,16 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( | |||
968 | osg->addr = sg_dma_address(sgent); | 1017 | osg->addr = sg_dma_address(sgent); |
969 | osg->en = en; | 1018 | osg->en = en; |
970 | osg->fn = sg_dma_len(sgent) / frame_bytes; | 1019 | osg->fn = sg_dma_len(sgent) / frame_bytes; |
1020 | if (port_window && dir == DMA_MEM_TO_DEV) { | ||
1021 | osg->ei = 1; | ||
1022 | /* | ||
1023 | * One frame covers the port_window and by configure | ||
1024 | * the source frame index to be -1 * (port_window - 1) | ||
1025 | * we instruct the sDMA that after a frame is processed | ||
1026 | * it should move back to the start of the window. | ||
1027 | */ | ||
1028 | osg->fi = -(port_window_bytes - 1); | ||
1029 | } | ||
971 | 1030 | ||
972 | if (d->using_ll) { | 1031 | if (d->using_ll) { |
973 | osg->t2_desc = dma_pool_alloc(od->desc_pool, GFP_ATOMIC, | 1032 | osg->t2_desc = dma_pool_alloc(od->desc_pool, GFP_ATOMIC, |