Skip to content

drivers: spi: nrfx_spim: use dmm #93487

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 37 additions & 37 deletions drivers/spi/spi_nrfx_spim.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#ifdef CONFIG_SOC_NRF54H20_GPD
#include <nrf/gpd.h>
#endif
#include <dmm.h>
#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
#include <nrfx_ppi.h>
#endif
Expand Down Expand Up @@ -91,13 +92,11 @@ struct spi_nrfx_config {
#endif
uint32_t wake_pin;
nrfx_gpiote_t wake_gpiote;
#ifdef CONFIG_DCACHE
uint32_t mem_attr;
#endif
#ifdef USE_CLOCK_REQUESTS
const struct device *clk_dev;
struct nrf_clock_spec clk_spec;
#endif
void *mem_reg;
};

static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context);
Expand Down Expand Up @@ -442,11 +441,6 @@ static void transfer_next_chunk(const struct device *dev)
}

memcpy(dev_data->tx_buffer, tx_buf, chunk_len);
#ifdef CONFIG_DCACHE
if (dev_config->mem_attr & DT_MEM_CACHEABLE) {
sys_cache_data_flush_range(dev_data->tx_buffer, chunk_len);
}
#endif
tx_buf = dev_data->tx_buffer;
}

Expand All @@ -463,10 +457,20 @@ static void transfer_next_chunk(const struct device *dev)

dev_data->chunk_len = chunk_len;

xfer.p_tx_buffer = tx_buf;
xfer.tx_length = spi_context_tx_buf_on(ctx) ? chunk_len : 0;
xfer.p_rx_buffer = rx_buf;
xfer.rx_length = spi_context_rx_buf_on(ctx) ? chunk_len : 0;
xfer.tx_length = spi_context_tx_buf_on(ctx) ? chunk_len : 0;
xfer.rx_length = spi_context_rx_buf_on(ctx) ? chunk_len : 0;

error = dmm_buffer_out_prepare(dev_config->mem_reg, tx_buf, xfer.tx_length,
(void **)&xfer.p_tx_buffer);
if (error != 0) {
goto out_alloc_failed;
}

error = dmm_buffer_in_prepare(dev_config->mem_reg, rx_buf, xfer.rx_length,
(void **)&xfer.p_rx_buffer);
if (error != 0) {
goto in_alloc_failed;
}

#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
if (xfer.rx_length == 1 && xfer.tx_length <= 1) {
Expand All @@ -489,6 +493,13 @@ static void transfer_next_chunk(const struct device *dev)
anomaly_58_workaround_clear(dev_data);
#endif
}

/* On nrfx_spim_xfer() error */
dmm_buffer_in_release(dev_config->mem_reg, rx_buf, xfer.rx_length,
(void **)&xfer.p_rx_buffer);
in_alloc_failed:
dmm_buffer_out_release(dev_config->mem_reg, (void **)&xfer.p_tx_buffer);
out_alloc_failed:
}

finish_transaction(dev, error);
Expand All @@ -498,9 +509,7 @@ static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context)
{
const struct device *dev = p_context;
struct spi_nrfx_data *dev_data = dev->data;
#ifdef CONFIG_DCACHE
const struct spi_nrfx_config *dev_config = dev->config;
#endif

if (p_event->type == NRFX_SPIM_EVENT_DONE) {
/* Chunk length is set to 0 when a transaction is aborted
Expand All @@ -514,15 +523,21 @@ static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context)
#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
anomaly_58_workaround_clear(dev_data);
#endif

if (spi_context_tx_buf_on(&dev_data->ctx)) {
dmm_buffer_out_release(dev_config->mem_reg,
(void **)p_event->xfer_desc.p_tx_buffer);
}

if (spi_context_rx_buf_on(&dev_data->ctx)) {
dmm_buffer_in_release(dev_config->mem_reg, dev_data->ctx.rx_buf,
dev_data->chunk_len, p_event->xfer_desc.p_rx_buffer);
}

#ifdef SPI_BUFFER_IN_RAM
if (spi_context_rx_buf_on(&dev_data->ctx) &&
p_event->xfer_desc.p_rx_buffer != NULL &&
p_event->xfer_desc.p_rx_buffer != dev_data->ctx.rx_buf) {
#ifdef CONFIG_DCACHE
if (dev_config->mem_attr & DT_MEM_CACHEABLE) {
sys_cache_data_invd_range(dev_data->rx_buffer, dev_data->chunk_len);
}
#endif
(void)memcpy(dev_data->ctx.rx_buf,
dev_data->rx_buffer,
dev_data->chunk_len);
Expand Down Expand Up @@ -799,7 +814,6 @@ static int spi_nrfx_deinit(const struct device *dev)
#define SPIM(idx) DT_NODELABEL(spi##idx)
#define SPIM_PROP(idx, prop) DT_PROP(SPIM(idx), prop)
#define SPIM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(SPIM(idx), prop)
#define SPIM_MEM_REGION(idx) DT_PHANDLE(SPIM(idx), memory_regions)

#define SPI_NRFX_SPIM_EXTENDED_CONFIG(idx) \
IF_ENABLED(NRFX_SPIM_EXTENDED_ENABLED, \
Expand All @@ -809,13 +823,6 @@ static int spi_nrfx_deinit(const struct device *dev)
()) \
))

#define SPIM_GET_MEM_ATTR(idx) \
COND_CODE_1(SPIM_HAS_PROP(idx, memory_regions), \
(COND_CODE_1(DT_NODE_HAS_PROP(SPIM_MEM_REGION(idx), zephyr_memory_attr), \
(DT_PROP(SPIM_MEM_REGION(idx), zephyr_memory_attr)), \
(0))), \
(0))

/* Fast instances depend on the global HSFLL clock controller (as they need
* to request the highest frequency from it to operate correctly), so they
* must be initialized after that controller driver, hence the default SPI
Expand All @@ -841,10 +848,10 @@ static int spi_nrfx_deinit(const struct device *dev)
IF_ENABLED(SPI_BUFFER_IN_RAM, \
(static uint8_t spim_##idx##_tx_buffer \
[CONFIG_SPI_NRFX_RAM_BUFFER_SIZE] \
SPIM_MEMORY_SECTION(idx); \
DMM_MEMORY_SECTION(SPIM(idx)); \
static uint8_t spim_##idx##_rx_buffer \
[CONFIG_SPI_NRFX_RAM_BUFFER_SIZE] \
SPIM_MEMORY_SECTION(idx);)) \
DMM_MEMORY_SECTION(SPIM(idx));)) \
static struct spi_nrfx_data spi_##idx##_data = { \
IF_ENABLED(CONFIG_MULTITHREADING, \
(SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx),)) \
Expand Down Expand Up @@ -881,15 +888,14 @@ static int spi_nrfx_deinit(const struct device *dev)
.wake_pin = NRF_DT_GPIOS_TO_PSEL_OR(SPIM(idx), wake_gpios, \
WAKE_PIN_NOT_USED), \
.wake_gpiote = WAKE_GPIOTE_INSTANCE(SPIM(idx)), \
IF_ENABLED(CONFIG_DCACHE, \
(.mem_attr = SPIM_GET_MEM_ATTR(idx),)) \
IF_ENABLED(USE_CLOCK_REQUESTS, \
(.clk_dev = SPIM_REQUESTS_CLOCK(SPIM(idx)) \
? DEVICE_DT_GET(DT_CLOCKS_CTLR(SPIM(idx))) \
: NULL, \
.clk_spec = { \
.frequency = NRF_CLOCK_CONTROL_FREQUENCY_MAX, \
},)) \
.mem_reg = DMM_DEV_TO_REG(SPIM(idx)), \
}; \
BUILD_ASSERT(!SPIM_HAS_PROP(idx, wake_gpios) || \
!(DT_GPIO_FLAGS(SPIM(idx), wake_gpios) & GPIO_ACTIVE_LOW),\
Expand All @@ -904,12 +910,6 @@ static int spi_nrfx_deinit(const struct device *dev)
POST_KERNEL, SPIM_INIT_PRIORITY(idx), \
&spi_nrfx_driver_api)

#define SPIM_MEMORY_SECTION(idx) \
COND_CODE_1(SPIM_HAS_PROP(idx, memory_regions), \
(__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \
SPIM_MEM_REGION(idx)))))), \
())

#define COND_NRF_SPIM_DEVICE(unused, prefix, i, _) \
IF_ENABLED(CONFIG_HAS_HW_NRF_SPIM##prefix##i, (SPI_NRFX_SPIM_DEFINE(prefix##i);))

Expand Down
4 changes: 2 additions & 2 deletions drivers/spi/spi_nrfx_spis.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ static int prepare_for_transfer(const struct device *dev,
return 0;

buffers_set_failed:
dmm_buffer_in_release(dev_config->mem_reg, rx_buf, rx_buf_len, rx_buf);
dmm_buffer_in_release(dev_config->mem_reg, rx_buf, rx_buf_len, dmm_rx_buf);
in_alloc_failed:
dmm_buffer_out_release(dev_config->mem_reg, (void *)tx_buf);
dmm_buffer_out_release(dev_config->mem_reg, (void *)dmm_tx_buf);
out_alloc_failed:
return err;
}
Expand Down
7 changes: 7 additions & 0 deletions tests/drivers/spi/spi_controller_peripheral/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@ config TESTED_SPI_MODE
2: CPOL 1 (Active low), CPHA 0 (leading)
3: CPOL 1 (Active low), CPHA 1 (trailing)

config PREALLOC_BUFFERS
bool "Preallocate buffers"
default y
help
Preallocate buffers used for transaction
using `memory-region` property.

source "Kconfig.zephyr"
9 changes: 6 additions & 3 deletions tests/drivers/spi/spi_controller_peripheral/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ static struct k_poll_event async_evt_spim =
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &async_sig_spim);

#define MEMORY_SECTION(node) \
COND_CODE_1(DT_NODE_HAS_PROP(node, memory_regions), \
(__attribute__((__section__( \
LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(node, memory_regions)))))), \
COND_CODE_1(IS_ENABLED(CONFIG_PREALLOC_BUFFERS), \
(COND_CODE_1(DT_NODE_HAS_PROP(node, memory_regions), \
(__attribute__((__section__( \
LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(node, \
memory_regions)))))), \
())), \
())

static uint8_t spim_buffer[32] MEMORY_SECTION(DT_BUS(DT_NODELABEL(dut_spi_dt)));
Expand Down
11 changes: 11 additions & 0 deletions tests/drivers/spi/spi_controller_peripheral/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,14 @@ tests:
- CONFIG_PM_DEVICE=y
- CONFIG_PM_DEVICE_RUNTIME=y
filter: CONFIG_SOC_FAMILY_NORDIC_NRF

drivers.spi.direct_xfer:
extra_configs:
- CONFIG_SPI_NRFX_RAM_BUFFER_SIZE=0
filter: CONFIG_SOC_FAMILY_NORDIC_NRF

drivers.spi.direct_xfer.no_prealloc:
extra_configs:
- CONFIG_SPI_NRFX_RAM_BUFFER_SIZE=0
- CONFIG_PREALLOC_BUFFERS=n
filter: CONFIG_SOC_FAMILY_NORDIC_NRF