|
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