|
20 | 20 | #include <zephyr/drivers/i2c.h> |
21 | 21 | #include <zephyr/pm/device.h> |
22 | 22 | #include <zephyr/pm/device_runtime.h> |
23 | | - |
| 23 | +#include <stm32_cache.h> |
24 | 24 | #include <zephyr/cache.h> |
25 | 25 | #include <zephyr/linker/linker-defs.h> |
26 | 26 | #include <zephyr/mem_mgmt/mem_attr.h> |
@@ -149,6 +149,68 @@ static int configure_dma(struct stream const *dma, struct dma_config *dma_cfg, |
149 | 149 |
|
150 | 150 | return 0; |
151 | 151 | } |
| 152 | + |
| 153 | +static void dma_xfer_start(const struct device *dev, struct i2c_msg *msg) |
| 154 | +{ |
| 155 | + const struct i2c_stm32_config *cfg = dev->config; |
| 156 | + struct i2c_stm32_data *data = dev->data; |
| 157 | + I2C_TypeDef *i2c = cfg->i2c; |
| 158 | + |
| 159 | + if ((msg->flags & I2C_MSG_READ) != 0U) { |
| 160 | + /* Configure RX DMA */ |
| 161 | + data->dma_blk_cfg.source_address = LL_I2C_DMA_GetRegAddr( |
| 162 | + cfg->i2c, LL_I2C_DMA_REG_DATA_RECEIVE); |
| 163 | + data->dma_blk_cfg.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; |
| 164 | + data->dma_blk_cfg.dest_address = (uint32_t)data->current.buf; |
| 165 | + data->dma_blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT; |
| 166 | + data->dma_blk_cfg.block_size = data->current.len; |
| 167 | + |
| 168 | + if (configure_dma(&cfg->rx_dma, &data->dma_rx_cfg, |
| 169 | + &data->dma_blk_cfg) != 0) { |
| 170 | + LOG_ERR("Problem setting up RX DMA"); |
| 171 | + return; |
| 172 | + } |
| 173 | + data->current.buf += msg->len; |
| 174 | + data->current.len -= msg->len; |
| 175 | + LL_I2C_EnableDMAReq_RX(i2c); |
| 176 | + } else { |
| 177 | + if (data->current.len != 0U) { |
| 178 | + /* Configure TX DMA */ |
| 179 | + data->dma_blk_cfg.source_address = (uint32_t)data->current.buf; |
| 180 | + data->dma_blk_cfg.source_addr_adj = DMA_ADDR_ADJ_INCREMENT; |
| 181 | + data->dma_blk_cfg.dest_address = LL_I2C_DMA_GetRegAddr( |
| 182 | + cfg->i2c, LL_I2C_DMA_REG_DATA_TRANSMIT); |
| 183 | + data->dma_blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; |
| 184 | + data->dma_blk_cfg.block_size = data->current.len; |
| 185 | + |
| 186 | + if (configure_dma(&cfg->tx_dma, &data->dma_tx_cfg, |
| 187 | + &data->dma_blk_cfg) != 0) { |
| 188 | + LOG_ERR("Problem setting up TX DMA"); |
| 189 | + return; |
| 190 | + } |
| 191 | + data->current.buf += data->current.len; |
| 192 | + data->current.len -= data->current.len; |
| 193 | + LL_I2C_EnableDMAReq_TX(i2c); |
| 194 | + } |
| 195 | + } |
| 196 | +} |
| 197 | + |
| 198 | +static void dma_finish(const struct device *dev, struct i2c_msg *msg) |
| 199 | +{ |
| 200 | + const struct i2c_stm32_config *cfg = dev->config; |
| 201 | + |
| 202 | + if ((msg->flags & I2C_MSG_READ) != 0U) { |
| 203 | + dma_stop(cfg->rx_dma.dev_dma, cfg->rx_dma.dma_channel); |
| 204 | + LL_I2C_DisableDMAReq_RX(cfg->i2c); |
| 205 | + if (!stm32_buf_in_nocache((uintptr_t)msg->buf, msg->len)) { |
| 206 | + sys_cache_data_invd_range(msg->buf, msg->len); |
| 207 | + } |
| 208 | + } else { |
| 209 | + dma_stop(cfg->tx_dma.dev_dma, cfg->tx_dma.dma_channel); |
| 210 | + LL_I2C_DisableDMAReq_TX(cfg->i2c); |
| 211 | + } |
| 212 | +} |
| 213 | + |
152 | 214 | #endif /* CONFIG_I2C_STM32_V2_DMA */ |
153 | 215 |
|
154 | 216 | static inline void msg_init(const struct device *dev, struct i2c_msg *msg, |
@@ -188,44 +250,7 @@ static inline void msg_init(const struct device *dev, struct i2c_msg *msg, |
188 | 250 |
|
189 | 251 | #ifdef CONFIG_I2C_STM32_V2_DMA |
190 | 252 | if (msg->len) { |
191 | | - if (msg->flags & I2C_MSG_READ) { |
192 | | - /* Configure RX DMA */ |
193 | | - data->dma_blk_cfg.source_address = LL_I2C_DMA_GetRegAddr( |
194 | | - cfg->i2c, LL_I2C_DMA_REG_DATA_RECEIVE); |
195 | | - data->dma_blk_cfg.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; |
196 | | - data->dma_blk_cfg.dest_address = (uint32_t)msg->buf; |
197 | | - data->dma_blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT; |
198 | | - data->dma_blk_cfg.block_size = msg->len; |
199 | | - |
200 | | - if (configure_dma(&cfg->rx_dma, &data->dma_rx_cfg, |
201 | | - &data->dma_blk_cfg) != 0) { |
202 | | - LOG_ERR("Problem setting up RX DMA"); |
203 | | - return; |
204 | | - } |
205 | | - data->current.buf += msg->len; |
206 | | - data->current.len -= msg->len; |
207 | | - LL_I2C_EnableDMAReq_RX(i2c); |
208 | | - } else { |
209 | | - if (data->current.len) { |
210 | | - /* Configure TX DMA */ |
211 | | - data->dma_blk_cfg.source_address = |
212 | | - (uint32_t)data->current.buf; |
213 | | - data->dma_blk_cfg.source_addr_adj = DMA_ADDR_ADJ_INCREMENT; |
214 | | - data->dma_blk_cfg.dest_address = LL_I2C_DMA_GetRegAddr( |
215 | | - cfg->i2c, LL_I2C_DMA_REG_DATA_TRANSMIT); |
216 | | - data->dma_blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; |
217 | | - data->dma_blk_cfg.block_size = msg->len; |
218 | | - |
219 | | - if (configure_dma(&cfg->tx_dma, &data->dma_tx_cfg, |
220 | | - &data->dma_blk_cfg) != 0) { |
221 | | - LOG_ERR("Problem setting up TX DMA"); |
222 | | - return; |
223 | | - } |
224 | | - data->current.buf += data->current.len; |
225 | | - data->current.len -= data->current.len; |
226 | | - LL_I2C_EnableDMAReq_TX(i2c); |
227 | | - } |
228 | | - } |
| 253 | + dma_xfer_start(dev, msg); |
229 | 254 | } |
230 | 255 | #endif /* CONFIG_I2C_STM32_V2_DMA */ |
231 | 256 |
|
@@ -288,16 +313,6 @@ static void i2c_stm32_master_mode_end(const struct device *dev) |
288 | 313 | } |
289 | 314 | #endif |
290 | 315 |
|
291 | | -#ifdef CONFIG_I2C_STM32_V2_DMA |
292 | | - if (data->current.msg->flags & I2C_MSG_READ) { |
293 | | - dma_stop(cfg->rx_dma.dev_dma, cfg->rx_dma.dma_channel); |
294 | | - LL_I2C_DisableDMAReq_RX(i2c); |
295 | | - } else { |
296 | | - dma_stop(cfg->tx_dma.dev_dma, cfg->tx_dma.dma_channel); |
297 | | - LL_I2C_DisableDMAReq_TX(i2c); |
298 | | - } |
299 | | -#endif /* CONFIG_I2C_STM32_V2_DMA */ |
300 | | - |
301 | 316 | k_sem_give(&data->device_sync_sem); |
302 | 317 | } |
303 | 318 |
|
@@ -599,17 +614,6 @@ void i2c_stm32_event(const struct device *dev) |
599 | 614 | LL_I2C_GenerateStopCondition(i2c); |
600 | 615 | } else { |
601 | 616 | i2c_stm32_disable_transfer_interrupts(dev); |
602 | | - |
603 | | -#ifdef CONFIG_I2C_STM32_V2_DMA |
604 | | - if (data->current.msg->flags & I2C_MSG_READ) { |
605 | | - dma_stop(cfg->rx_dma.dev_dma, cfg->rx_dma.dma_channel); |
606 | | - LL_I2C_DisableDMAReq_RX(i2c); |
607 | | - } else { |
608 | | - dma_stop(cfg->tx_dma.dev_dma, cfg->tx_dma.dma_channel); |
609 | | - LL_I2C_DisableDMAReq_TX(i2c); |
610 | | - } |
611 | | -#endif /* CONFIG_I2C_STM32_V2_DMA */ |
612 | | - |
613 | 617 | k_sem_give(&data->device_sync_sem); |
614 | 618 | } |
615 | 619 | } |
@@ -694,6 +698,9 @@ static int i2c_stm32_msg_write(const struct device *dev, struct i2c_msg *msg, |
694 | 698 | k_sem_take(&data->device_sync_sem, K_FOREVER); |
695 | 699 | is_timeout = true; |
696 | 700 | } |
| 701 | +#ifdef CONFIG_I2C_STM32_V2_DMA |
| 702 | + dma_finish(dev, msg); |
| 703 | +#endif |
697 | 704 |
|
698 | 705 | if (data->current.is_nack || data->current.is_err || |
699 | 706 | data->current.is_arlo || is_timeout) { |
@@ -753,13 +760,9 @@ static int i2c_stm32_msg_read(const struct device *dev, struct i2c_msg *msg, |
753 | 760 | k_sem_take(&data->device_sync_sem, K_FOREVER); |
754 | 761 | is_timeout = true; |
755 | 762 | } |
756 | | -#if defined(CONFIG_I2C_STM32_V2_DMA) |
757 | | - if (!stm32_buf_in_nocache((uintptr_t)msg->buf, msg->len)) { |
758 | | - LOG_DBG("Rx buffer at %p (len %zu) is in cached memory; invalidating cache", |
759 | | - msg->buf, msg->len); |
760 | | - sys_cache_data_invd_range((void *)msg->buf, msg->len); |
761 | | - } |
762 | | -#endif /* CONFIG_I2C_STM32_V2_DMA */ |
| 763 | +#ifdef CONFIG_I2C_STM32_V2_DMA |
| 764 | + dma_finish(dev, msg); |
| 765 | +#endif |
763 | 766 |
|
764 | 767 | if (data->current.is_nack || data->current.is_err || |
765 | 768 | data->current.is_arlo || is_timeout) { |
|
0 commit comments