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
9 changes: 9 additions & 0 deletions drivers/mspi/Kconfig.dw
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ config MSPI_DW

if MSPI_DW

config MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE
bool "Handle FIFO in system workqueue"
help
When the driver does not use DMA for transferring data to/from the
SSI FIFOs, handling of those may take a significant amount of time.
It may be destructive for some applications if that time is spent
in the interrupt context. This option allows offloading the job to
the system workqueue.

config MSPI_DW_TXD_DIV
int "Designware SSI TX Drive edge divisor"
default 4
Expand Down
100 changes: 82 additions & 18 deletions drivers/mspi/mspi_dw.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@
/* For locking of controller configuration. */
struct k_sem cfg_lock;
struct mspi_xfer xfer;

#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE)
struct k_work fifo_work;
const struct device *dev;
uint32_t imr;
#endif
};

struct mspi_dw_config {
Expand Down Expand Up @@ -111,8 +117,8 @@
DEFINE_MM_REG_RD(txflr, 0x20)
DEFINE_MM_REG_RD(rxflr, 0x24)
DEFINE_MM_REG_RD(sr, 0x28)
DEFINE_MM_REG_WR(imr, 0x2c)
DEFINE_MM_REG_RD_WR(imr, 0x2c)
DEFINE_MM_REG_RD(isr, 0x30)

Check notice on line 121 in drivers/mspi/mspi_dw.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/mspi/mspi_dw.c:121 -DEFINE_MM_REG_RD_WR(imr, 0x2c) +DEFINE_MM_REG_RD_WR(imr, 0x2c)
DEFINE_MM_REG_RD(risr, 0x34)
DEFINE_MM_REG_RD_WR(dr, 0x60)
DEFINE_MM_REG_WR(rx_sample_dly, 0xf0)
Expand Down Expand Up @@ -218,6 +224,8 @@
write_dr(dev, dummy_val);
} while (--dummy_bytes);

dev_data->dummy_bytes = 0;

/* Set the TX start level to 0, so that the transmission will be
* started now if it hasn't been yet. The threshold value is also
* set to 0 here, but it doesn't really matter, as the interrupt
Expand Down Expand Up @@ -280,7 +288,18 @@
return false;
}

static void mspi_dw_isr(const struct device *dev)
static inline void set_imr(const struct device *dev, uint32_t imr)
{
#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE)
struct mspi_dw_data *dev_data = dev->data;

dev_data->imr = imr;
#else
write_imr(dev, imr);
#endif
}

static void handle_fifos(const struct device *dev)
{
struct mspi_dw_data *dev_data = dev->data;
const struct mspi_xfer_packet *packet =
Expand All @@ -302,42 +321,82 @@
finished = true;
}
} else {
uint32_t int_status = read_isr(dev);
for (;;) {
/* Use RISR, not ISR, because when this function is
* executed through the system workqueue, all interrupts
* are masked (IMR is 0).
*/
uint32_t int_status = read_risr(dev);

do {
if (int_status & ISR_RXFIS_BIT) {
if (int_status & RISR_RXFIR_BIT) {
if (read_rx_fifo(dev, packet)) {
finished = true;
break;
}

if (read_risr(dev) & RISR_RXOIR_BIT) {
if (int_status & RISR_RXOIR_BIT) {
finished = true;
break;
}

int_status = read_isr(dev);
/* Refresh interrupt status, as during reading
* from the RX FIFO, the TX FIFO status might
* have changed.
*/
int_status = read_risr(dev);
}

if (int_status & ISR_TXEIS_BIT) {
if (tx_dummy_bytes(dev)) {
/* All the required dummy bytes were
* written to the FIFO; disable the TXE
* interrupt, as it's no longer needed.
*/
write_imr(dev, IMR_RXFIM_BIT);
}
if (dev_data->dummy_bytes == 0 ||
!(int_status & RISR_TXEIR_BIT)) {
break;

Check notice on line 351 in drivers/mspi/mspi_dw.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/mspi/mspi_dw.c:351 - if (dev_data->dummy_bytes == 0 || - !(int_status & RISR_TXEIR_BIT)) { + if (dev_data->dummy_bytes == 0 || !(int_status & RISR_TXEIR_BIT)) {
}

int_status = read_isr(dev);
if (tx_dummy_bytes(dev)) {
/* All the required dummy bytes were written
* to the FIFO; disable the TXE interrupt,
* as it's no longer needed.
*/
set_imr(dev, IMR_RXFIM_BIT);
}
} while (int_status != 0);
}
}

if (finished) {
write_imr(dev, 0);
set_imr(dev, 0);

k_sem_give(&dev_data->finished);
}
}

#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE)
static void fifo_work_handler(struct k_work *work)
{
struct mspi_dw_data *dev_data =
CONTAINER_OF(work, struct mspi_dw_data, fifo_work);
const struct device *dev = dev_data->dev;

Check notice on line 376 in drivers/mspi/mspi_dw.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/mspi/mspi_dw.c:376 - struct mspi_dw_data *dev_data = - CONTAINER_OF(work, struct mspi_dw_data, fifo_work); + struct mspi_dw_data *dev_data = CONTAINER_OF(work, struct mspi_dw_data, fifo_work);

handle_fifos(dev);

write_imr(dev, dev_data->imr);
}
#endif

static void mspi_dw_isr(const struct device *dev)
{
#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE)
struct mspi_dw_data *dev_data = dev->data;
int rc;

dev_data->imr = read_imr(dev);
write_imr(dev, 0);

rc = k_work_submit(&dev_data->fifo_work);
if (rc < 0) {
LOG_ERR("k_work_submit failed: %d\n", rc);
}
#else
handle_fifos(dev);
#endif

vendor_specific_irq_clear(dev);
}
Expand Down Expand Up @@ -1426,6 +1485,11 @@
k_sem_init(&dev_data->cfg_lock, 1, 1);
k_sem_init(&dev_data->ctx_lock, 1, 1);

#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE)
dev_data->dev = dev;
k_work_init(&dev_data->fifo_work, fifo_work_handler);
#endif

for (ce_gpio = dev_config->ce_gpios;
ce_gpio < &dev_config->ce_gpios[dev_config->ce_gpios_len];
ce_gpio++) {
Expand Down
23 changes: 23 additions & 0 deletions tests/drivers/mspi/flash/boards/nrf54h20dk_nrf54h20_cpuapp.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

/ {
aliases {
mspi0 = &exmif;
};
};

&gpio6 {
status = "okay";
};

&exmif {
status = "okay";
};

&mx25uw63 {
status = "okay";
};
24 changes: 14 additions & 10 deletions tests/drivers/mspi/flash/testcase.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# Copyright (c) 2024 Ambiq Micro Inc. <www.ambiq.com>
# SPDX-License-Identifier: Apache-2.0

common:
tags:
- drivers
- mspi
- flash
harness: ztest

tests:
drivers.mspi.flash:
tags:
- drivers
- mspi
- flash
filter: dt_compat_enabled("zephyr,mspi-emul-flash")
or dt_compat_enabled("jedec,spi-nor") or dt_compat_enabled("jedec,mspi-nor")
or dt_compat_enabled("mspi-atxp032") or dt_compat_enabled("mspi-is25xX0xx")
harness: ztest
platform_allow:
- native_sim
- apollo3p_evb
Expand All @@ -20,15 +22,17 @@ tests:
- apollo3p_evb
- apollo510_evb
drivers.mspi.flash.xip_read:
tags:
- drivers
- mspi
- flash
filter: dt_compat_enabled("mspi-is25xX0xx")
harness: ztest
platform_allow:
- apollo510_evb
integration_platforms:
- apollo510_evb
extra_configs:
- CONFIG_FLASH_MSPI_XIP_READ=y
drivers.mspi.flash.mspi_dw_system_workqueue:
filter: dt_alias_exists("mspi0") and dt_compat_enabled("jedec,mspi-nor")
and CONFIG_MSPI_DW
integration_platforms:
- nrf54h20dk/nrf54h20/cpuapp
extra_configs:
- CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE=y
Loading