drivers: stm32: SPI: Check that SPI buffers are in a nocache region
DMA only works with non-cached memory regions in H7. Check them and return an error if they don't match this condition. Signed-off-by: Daniel Gaston Ochoa <dgastonochoa@gmail.com>
This commit is contained in:
parent
19f33b8ecb
commit
1b3e2d98e4
1 changed files with 65 additions and 0 deletions
|
@ -51,6 +51,36 @@ LOG_MODULE_REGISTER(spi_ll_stm32);
|
||||||
#endif /* CONFIG_SOC_SERIES_STM32MP1X */
|
#endif /* CONFIG_SOC_SERIES_STM32MP1X */
|
||||||
|
|
||||||
#ifdef CONFIG_SPI_STM32_DMA
|
#ifdef CONFIG_SPI_STM32_DMA
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOC_SERIES_STM32H7X
|
||||||
|
|
||||||
|
#define IS_NOCACHE_MEM_REGION(node_id) \
|
||||||
|
COND_CODE_1(DT_ENUM_HAS_VALUE(node_id, zephyr_memory_attr, RAM_NOCACHE), \
|
||||||
|
(1), \
|
||||||
|
(0))
|
||||||
|
|
||||||
|
#define GET_MEM_REGION(node_id) \
|
||||||
|
{ \
|
||||||
|
.start = DT_REG_ADDR(node_id), \
|
||||||
|
.end = (DT_REG_ADDR(node_id) + DT_REG_SIZE(node_id)) - 1, \
|
||||||
|
},
|
||||||
|
|
||||||
|
#define GET_MEM_REGION_IF_NOCACHE(node_id) \
|
||||||
|
COND_CODE_1(IS_NOCACHE_MEM_REGION(node_id), \
|
||||||
|
( \
|
||||||
|
GET_MEM_REGION(node_id) \
|
||||||
|
), ())
|
||||||
|
|
||||||
|
struct mem_region {
|
||||||
|
uintptr_t start;
|
||||||
|
uintptr_t end;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mem_region nocache_mem_regions[] = {
|
||||||
|
DT_MEMORY_ATTR_FOREACH_NODE(GET_MEM_REGION_IF_NOCACHE)
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_SOC_SERIES_STM32H7X */
|
||||||
|
|
||||||
/* dummy value used for transferring NOP when tx buf is null
|
/* dummy value used for transferring NOP when tx buf is null
|
||||||
* and use as dummy sink for when rx buf is null
|
* and use as dummy sink for when rx buf is null
|
||||||
*/
|
*/
|
||||||
|
@ -723,6 +753,34 @@ static int wait_dma_rx_tx_done(const struct device *dev)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOC_SERIES_STM32H7X
|
||||||
|
static bool buf_in_nocache(uintptr_t buf, size_t len_bytes)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < ARRAY_SIZE(nocache_mem_regions); i++) {
|
||||||
|
const struct mem_region *mem_reg = &nocache_mem_regions[i];
|
||||||
|
|
||||||
|
const bool buf_within_bounds =
|
||||||
|
(buf >= mem_reg->start) && ((buf + len_bytes - 1) <= mem_reg->end);
|
||||||
|
if (buf_within_bounds) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool spi_buf_set_in_nocache(const struct spi_buf_set *bufs)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < bufs->count; i++) {
|
||||||
|
const struct spi_buf *buf = &bufs->buffers[i];
|
||||||
|
|
||||||
|
if (!buf_in_nocache((uintptr_t)buf->buf, buf->len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SOC_SERIES_STM32H7X */
|
||||||
|
|
||||||
static int transceive_dma(const struct device *dev,
|
static int transceive_dma(const struct device *dev,
|
||||||
const struct spi_config *config,
|
const struct spi_config *config,
|
||||||
const struct spi_buf_set *tx_bufs,
|
const struct spi_buf_set *tx_bufs,
|
||||||
|
@ -744,6 +802,13 @@ static int transceive_dma(const struct device *dev,
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOC_SERIES_STM32H7X
|
||||||
|
if ((tx_bufs != NULL && !spi_buf_set_in_nocache(tx_bufs)) ||
|
||||||
|
(rx_bufs != NULL && !spi_buf_set_in_nocache(rx_bufs))) {
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SOC_SERIES_STM32H7X */
|
||||||
|
|
||||||
spi_context_lock(&data->ctx, asynchronous, cb, userdata, config);
|
spi_context_lock(&data->ctx, asynchronous, cb, userdata, config);
|
||||||
|
|
||||||
k_sem_reset(&data->status_sem);
|
k_sem_reset(&data->status_sem);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue