summaryrefslogtreecommitdiffstats
path: root/drivers/dma/stm32-dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/stm32-dma.c')
-rw-r--r--drivers/dma/stm32-dma.c90
1 files changed, 77 insertions, 13 deletions
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index dde796686736..88d9c6c4389f 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -1042,33 +1042,97 @@ static u32 stm32_dma_get_remaining_bytes(struct stm32_dma_chan *chan)
1042 return ndtr << width; 1042 return ndtr << width;
1043} 1043}
1044 1044
1045/**
1046 * stm32_dma_is_current_sg - check that expected sg_req is currently transferred
1047 * @chan: dma channel
1048 *
1049 * This function called when IRQ are disable, checks that the hardware has not
1050 * switched on the next transfer in double buffer mode. The test is done by
1051 * comparing the next_sg memory address with the hardware related register
1052 * (based on CT bit value).
1053 *
1054 * Returns true if expected current transfer is still running or double
1055 * buffer mode is not activated.
1056 */
1057static bool stm32_dma_is_current_sg(struct stm32_dma_chan *chan)
1058{
1059 struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
1060 struct stm32_dma_sg_req *sg_req;
1061 u32 dma_scr, dma_smar, id;
1062
1063 id = chan->id;
1064 dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id));
1065
1066 if (!(dma_scr & STM32_DMA_SCR_DBM))
1067 return true;
1068
1069 sg_req = &chan->desc->sg_req[chan->next_sg];
1070
1071 if (dma_scr & STM32_DMA_SCR_CT) {
1072 dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM0AR(id));
1073 return (dma_smar == sg_req->chan_reg.dma_sm0ar);
1074 }
1075
1076 dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM1AR(id));
1077
1078 return (dma_smar == sg_req->chan_reg.dma_sm1ar);
1079}
1080
1045static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, 1081static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
1046 struct stm32_dma_desc *desc, 1082 struct stm32_dma_desc *desc,
1047 u32 next_sg) 1083 u32 next_sg)
1048{ 1084{
1049 u32 modulo, burst_size; 1085 u32 modulo, burst_size;
1050 u32 residue = 0; 1086 u32 residue;
1087 u32 n_sg = next_sg;
1088 struct stm32_dma_sg_req *sg_req = &chan->desc->sg_req[chan->next_sg];
1051 int i; 1089 int i;
1052 1090
1053 /* 1091 /*
1054 * In cyclic mode, for the last period, residue = remaining bytes from 1092 * Calculate the residue means compute the descriptors
1055 * NDTR 1093 * information:
1094 * - the sg_req currently transferred
1095 * - the Hardware remaining position in this sg (NDTR bits field).
1096 *
1097 * A race condition may occur if DMA is running in cyclic or double
1098 * buffer mode, since the DMA register are automatically reloaded at end
1099 * of period transfer. The hardware may have switched to the next
1100 * transfer (CT bit updated) just before the position (SxNDTR reg) is
1101 * read.
1102 * In this case the SxNDTR reg could (or not) correspond to the new
1103 * transfer position, and not the expected one.
1104 * The strategy implemented in the stm32 driver is to:
1105 * - read the SxNDTR register
1106 * - crosscheck that hardware is still in current transfer.
1107 * In case of switch, we can assume that the DMA is at the beginning of
1108 * the next transfer. So we approximate the residue in consequence, by
1109 * pointing on the beginning of next transfer.
1110 *
1111 * This race condition doesn't apply for none cyclic mode, as double
1112 * buffer is not used. In such situation registers are updated by the
1113 * software.
1056 */ 1114 */
1057 if (chan->desc->cyclic && next_sg == 0) { 1115
1058 residue = stm32_dma_get_remaining_bytes(chan); 1116 residue = stm32_dma_get_remaining_bytes(chan);
1059 goto end; 1117
1118 if (!stm32_dma_is_current_sg(chan)) {
1119 n_sg++;
1120 if (n_sg == chan->desc->num_sgs)
1121 n_sg = 0;
1122 residue = sg_req->len;
1060 } 1123 }
1061 1124
1062 /* 1125 /*
1063 * For all other periods in cyclic mode, and in sg mode, 1126 * In cyclic mode, for the last period, residue = remaining bytes
1064 * residue = remaining bytes from NDTR + remaining periods/sg to be 1127 * from NDTR,
1065 * transferred 1128 * else for all other periods in cyclic mode, and in sg mode,
1129 * residue = remaining bytes from NDTR + remaining
1130 * periods/sg to be transferred
1066 */ 1131 */
1067 for (i = next_sg; i < desc->num_sgs; i++) 1132 if (!chan->desc->cyclic || n_sg != 0)
1068 residue += desc->sg_req[i].len; 1133 for (i = n_sg; i < desc->num_sgs; i++)
1069 residue += stm32_dma_get_remaining_bytes(chan); 1134 residue += desc->sg_req[i].len;
1070 1135
1071end:
1072 if (!chan->mem_burst) 1136 if (!chan->mem_burst)
1073 return residue; 1137 return residue;
1074 1138