diff options
Diffstat (limited to 'drivers/dma/stm32-dma.c')
-rw-r--r-- | drivers/dma/stm32-dma.c | 90 |
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 | */ | ||
1057 | static 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 | |||
1045 | static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, | 1081 | static 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 | ||
1071 | end: | ||
1072 | if (!chan->mem_burst) | 1136 | if (!chan->mem_burst) |
1073 | return residue; | 1137 | return residue; |
1074 | 1138 | ||