Skip to content

Commit

Permalink
[nrf noup] drivers: spi_dw: add custom EXMIF peripheral handling
Browse files Browse the repository at this point in the history
The Synopsys Designware SPI peripheral core is wrapped in hardware that
manages interrupts, power and clock. The SPI core registers are shifted
by 0x500 bytes.
Before the SPI core is used, the power and clock must be enabled by
writing to EXMIF.TASKS_START register.
Interrupts must be enabled by writing to EXMIF.INTENSET/INTENCLR
registers.

The SER register must be configured unconditionally during peripheral
setup. Otherwise, the serial transaction does not complete.

Signed-off-by: Rafał Kuźnia <rafal.kuznia@nordicsemi.no>
  • Loading branch information
e-rk authored and carlescufi committed May 9, 2024
1 parent 52cf91a commit 7ea6937
Showing 1 changed file with 20 additions and 1 deletion.
21 changes: 20 additions & 1 deletion drivers/spi/spi_dw.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ LOG_MODULE_REGISTER(spi_dw);
#include <zephyr/drivers/pinctrl.h>
#endif

#ifdef CONFIG_HAS_NRFX
#include <nrfx.h>
#endif

static inline bool spi_dw_is_slave(struct spi_dw_data *spi)
{
return (IS_ENABLED(CONFIG_SPI_SLAVE) &&
Expand Down Expand Up @@ -257,6 +261,7 @@ static int spi_dw_configure(const struct device *dev,
/* Baud rate and Slave select, for master only */
write_baudr(dev, SPI_DW_CLK_DIVIDER(info->clock_frequency,
config->frequency));
write_ser(dev, BIT(config->slave));
}

if (spi_dw_is_slave(spi)) {
Expand Down Expand Up @@ -499,6 +504,10 @@ void spi_dw_isr(const struct device *dev)
uint32_t int_status;
int error;

#ifdef CONFIG_HAS_NRFX
NRF_EXMIF->EVENTS_CORE = 0;
#endif

int_status = read_isr(dev);

LOG_DBG("SPI %p int_status 0x%x - (tx: %d, rx: %d)", dev, int_status,
Expand Down Expand Up @@ -544,6 +553,11 @@ int spi_dw_init(const struct device *dev)

DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);

#ifdef CONFIG_HAS_NRFX
NRF_EXMIF->INTENSET = BIT(0);
NRF_EXMIF->TASKS_START = 1;
#endif

info->config_func();

/* Masking interrupt and making sure controller is disabled */
Expand All @@ -562,6 +576,11 @@ int spi_dw_init(const struct device *dev)
return 0;
}

#define REG_ADDR(inst) \
COND_CODE_1(DT_NODE_HAS_COMPAT(DT_DRV_INST(inst), nordic_nrf_exmif), \
(Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(core, DT_DRV_INST(inst))), \
(DEVICE_MMIO_ROM_INIT(DT_DRV_INST(inst))))

#define SPI_CFG_IRQS_SINGLE_ERR_LINE(inst) \
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, rx_avail, irq), \
DT_INST_IRQ_BY_NAME(inst, rx_avail, priority), \
Expand Down Expand Up @@ -634,7 +653,7 @@ COND_CODE_1(IS_EQ(DT_NUM_IRQS(DT_DRV_INST(inst)), 1), \
SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(inst), ctx) \
}; \
static const struct spi_dw_config spi_dw_config_##inst = { \
DEVICE_MMIO_ROM_INIT(DT_DRV_INST(inst)), \
REG_ADDR(inst), \
.clock_frequency = COND_CODE_1( \
DT_NODE_HAS_PROP(DT_INST_PHANDLE(inst, clocks), clock_frequency), \
(DT_INST_PROP_BY_PHANDLE(inst, clocks, clock_frequency)), \
Expand Down

0 comments on commit 7ea6937

Please sign in to comment.