Skip to content
Merged
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
108 changes: 51 additions & 57 deletions drivers/spi/spi_nrfx_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ struct spi_nrfx_data {
const struct device *dev;
size_t chunk_len;
bool busy;
bool initialized;
};

struct spi_nrfx_config {
nrfx_spi_t spi;
nrfx_spi_config_t config;
nrfx_spi_config_t def_config;
};

static void event_handler(const nrfx_spi_evt_t *p_event, void *p_context);

static inline struct spi_nrfx_data *get_dev_data(const struct device *dev)
{
return dev->data;
Expand Down Expand Up @@ -86,17 +89,19 @@ static inline nrf_spi_bit_order_t get_nrf_spi_bit_order(uint16_t operation)
static int configure(const struct device *dev,
const struct spi_config *spi_cfg)
{
struct spi_context *ctx = &get_dev_data(dev)->ctx;
const nrfx_spi_t *spi = &get_dev_config(dev)->spi;
struct spi_nrfx_data *dev_data = get_dev_data(dev);
const struct spi_nrfx_config *dev_config = get_dev_config(dev);
struct spi_context *ctx = &dev_data->ctx;
nrfx_spi_config_t config;
nrfx_err_t result;

if (spi_context_configured(ctx, spi_cfg)) {
if (dev_data->initialized && spi_context_configured(ctx, spi_cfg)) {
/* Already configured. No need to do it again. */
return 0;
}

if (SPI_OP_MODE_GET(spi_cfg->operation) != SPI_OP_MODE_MASTER) {
LOG_ERR("Slave mode is not supported on %s",
dev->name);
LOG_ERR("Slave mode is not supported on %s", dev->name);
return -EINVAL;
}

Expand All @@ -111,8 +116,7 @@ static int configure(const struct device *dev,
}

if (SPI_WORD_SIZE_GET(spi_cfg->operation) != 8) {
LOG_ERR("Word sizes other than 8 bits"
" are not supported");
LOG_ERR("Word sizes other than 8 bits are not supported");
return -EINVAL;
}

Expand All @@ -121,15 +125,29 @@ static int configure(const struct device *dev,
return -EINVAL;
}

config = dev_config->def_config;

config.frequency = get_nrf_spi_frequency(spi_cfg->frequency);
config.mode = get_nrf_spi_mode(spi_cfg->operation);
config.bit_order = get_nrf_spi_bit_order(spi_cfg->operation);

if (dev_data->initialized) {
nrfx_spi_uninit(&dev_config->spi);
dev_data->initialized = false;
}

result = nrfx_spi_init(&dev_config->spi, &config,
event_handler, dev_data);
if (result != NRFX_SUCCESS) {
LOG_ERR("Failed to initialize nrfx driver: %08x", result);
return -EIO;
}

dev_data->initialized = true;

ctx->config = spi_cfg;
spi_context_cs_configure(ctx);

nrf_spi_configure(spi->p_reg,
get_nrf_spi_mode(spi_cfg->operation),
get_nrf_spi_bit_order(spi_cfg->operation));
nrf_spi_frequency_set(spi->p_reg,
get_nrf_spi_frequency(spi_cfg->frequency));

return 0;
}

Expand Down Expand Up @@ -167,6 +185,18 @@ static void transfer_next_chunk(const struct device *dev)
dev_data->busy = false;
}

static void event_handler(const nrfx_spi_evt_t *p_event, void *p_context)
{
struct spi_nrfx_data *dev_data = p_context;

if (p_event->type == NRFX_SPI_EVENT_DONE) {
spi_context_update_tx(&dev_data->ctx, 1, dev_data->chunk_len);
spi_context_update_rx(&dev_data->ctx, 1, dev_data->chunk_len);

transfer_next_chunk(dev_data->dev);
}
}

static int transceive(const struct device *dev,
const struct spi_config *spi_cfg,
const struct spi_buf_set *tx_bufs,
Expand Down Expand Up @@ -242,40 +272,6 @@ static const struct spi_driver_api spi_nrfx_driver_api = {
};


static void event_handler(const nrfx_spi_evt_t *p_event, void *p_context)
{
struct spi_nrfx_data *dev_data = p_context;

if (p_event->type == NRFX_SPI_EVENT_DONE) {
spi_context_update_tx(&dev_data->ctx, 1, dev_data->chunk_len);
spi_context_update_rx(&dev_data->ctx, 1, dev_data->chunk_len);

transfer_next_chunk(dev_data->dev);
}
}

static int init_spi(const struct device *dev)
{
struct spi_nrfx_data *dev_data = get_dev_data(dev);
nrfx_err_t result;

dev_data->dev = dev;

/* This sets only default values of frequency, mode and bit order.
* The proper ones are set in configure() when a transfer is started.
*/
result = nrfx_spi_init(&get_dev_config(dev)->spi,
&get_dev_config(dev)->config,
event_handler,
dev_data);
if (result != NRFX_SUCCESS) {
LOG_ERR("Failed to initialize device: %s", dev->name);
return -EBUSY;
}

return 0;
}

#ifdef CONFIG_PM_DEVICE
static int spi_nrfx_pm_control(const struct device *dev,
enum pm_device_action action)
Expand All @@ -286,13 +282,14 @@ static int spi_nrfx_pm_control(const struct device *dev,

switch (action) {
case PM_DEVICE_ACTION_RESUME:
ret = init_spi(dev);
/* Force reconfiguration before next transfer */
data->ctx.config = NULL;
/* No action needed at this point, nrfx_spi_init() will be
* called at configuration before the next transfer.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as previous comment

break;

case PM_DEVICE_ACTION_SUSPEND:
nrfx_spi_uninit(&config->spi);
data->initialized = false;
break;

default:
Expand Down Expand Up @@ -332,26 +329,23 @@ static int spi_nrfx_pm_control(const struct device *dev,
{ \
IRQ_CONNECT(DT_IRQN(SPI(idx)), DT_IRQ(SPI(idx), priority), \
nrfx_isr, nrfx_spi_##idx##_irq_handler, 0); \
int err = init_spi(dev); \
spi_context_unlock_unconditionally(&get_dev_data(dev)->ctx); \
return err; \
return 0; \
} \
static struct spi_nrfx_data spi_##idx##_data = { \
SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx), \
SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx), \
.dev = DEVICE_DT_GET(SPI(idx)), \
.busy = false, \
}; \
static const struct spi_nrfx_config spi_##idx##z_config = { \
.spi = NRFX_SPI_INSTANCE(idx), \
.config = { \
.def_config = { \
.sck_pin = SPI_PROP(idx, sck_pin), \
.mosi_pin = SPI_PROP(idx, mosi_pin), \
.miso_pin = SPI_PROP(idx, miso_pin), \
.ss_pin = NRFX_SPI_PIN_NOT_USED, \
.orc = CONFIG_SPI_##idx##_NRF_ORC, \
.frequency = NRF_SPI_FREQ_4M, \
.mode = NRF_SPI_MODE_0, \
.bit_order = NRF_SPI_BIT_ORDER_MSB_FIRST, \
.miso_pull = SPI_NRFX_MISO_PULL(idx), \
} \
}; \
Expand Down
Loading