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
12 changes: 11 additions & 1 deletion drivers/flash/flash_mspi_nor.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,9 @@ static int acquire(const struct device *dev)
struct flash_mspi_nor_data *dev_data = dev->data;
int rc;

#if defined(CONFIG_MULTITHREADING)
k_sem_take(&dev_data->acquired, K_FOREVER);
#endif

rc = pm_device_runtime_get(dev_config->bus);
if (rc < 0) {
Expand Down Expand Up @@ -269,21 +271,27 @@ static int acquire(const struct device *dev)
(void)pm_device_runtime_put(dev_config->bus);
}

#if defined(CONFIG_MULTITHREADING)
k_sem_give(&dev_data->acquired);
#endif

return rc;
}

static void release(const struct device *dev)
{
const struct flash_mspi_nor_config *dev_config = dev->config;
struct flash_mspi_nor_data *dev_data = dev->data;

/* This releases the MSPI controller. */
(void)mspi_get_channel_status(dev_config->bus, 0);

(void)pm_device_runtime_put(dev_config->bus);

#if defined(CONFIG_MULTITHREADING)
struct flash_mspi_nor_data *dev_data = dev->data;

k_sem_give(&dev_data->acquired);
#endif
}

static inline uint32_t dev_flash_size(const struct device *dev)
Expand Down Expand Up @@ -1215,7 +1223,9 @@ static int drv_init(const struct device *dev)
}
}

#if defined(CONFIG_MULTITHREADING)
k_sem_init(&dev_data->acquired, 1, K_SEM_MAX_LIMIT);
#endif

return pm_device_driver_init(dev, dev_pm_action_cb);
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/flash/flash_mspi_nor.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ struct flash_mspi_nor_config {
};

struct flash_mspi_nor_data {
#if defined(CONFIG_MULTITHREADING)
struct k_sem acquired;
#endif
struct mspi_xfer_packet packet;
struct mspi_xfer xfer;
struct jesd216_erase_type erase_types[JESD216_NUM_ERASE_TYPES];
Expand Down
110 changes: 90 additions & 20 deletions drivers/mspi/mspi_dw.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,16 @@
bool standard_spi;
bool suspended;

#if defined(CONFIG_MULTITHREADING)
struct k_sem finished;
/* For synchronization of API calls made from different contexts. */
struct k_sem ctx_lock;
/* For locking of controller configuration. */
struct k_sem cfg_lock;
#else
volatile bool finished;
bool cfg_lock;
#endif
struct mspi_xfer xfer;

#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE)
Expand Down Expand Up @@ -245,9 +250,12 @@
uint8_t *buf_pos = dev_data->buf_pos;
const uint8_t *buf_end = &packet->data_buf[packet->num_bytes];
uint8_t bytes_per_frame_exp = dev_data->bytes_per_frame_exp;
/* See `room` in tx_data(). */
uint32_t in_fifo = 1;
uint32_t remaining_frames;
uint32_t in_fifo = FIELD_GET(RXFLR_RXTFL_MASK, read_rxflr(dev));

if (in_fifo == 0) {
return false;
}

do {
uint32_t data = read_dr(dev);
Expand Down Expand Up @@ -322,28 +330,37 @@
}
} else {
for (;;) {
/* Always read everything from the RX FIFO, regardless
* of the interrupt status.
* tx_dummy_bytes() subtracts the number of items that
* are present in the RX FIFO from the number of dummy
* bytes it is allowed to send, so it can potentially
* not fill the TX FIFO above its transfer start level
* in some iteration of this loop. If in such case the
* interrupt handler exited without emptying the RX FIFO
* (seeing the RXFIS flag not set due to not enough
* items in the RX FIFO), this could lead to a situation
* in which a transfer stopped temporarily (after the TX
* FIFO got empty) is not resumed (since the TX FIFO is
* not filled above its transfer start level), so no
* further dummy bytes are transmitted and the RX FIFO
* has no chance to get new entries, hence no further
* interrupts are generated and the transfer gets stuck.
*/
if (read_rx_fifo(dev, packet)) {
finished = true;
break;
}

/* 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);

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

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

/* 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 & RISR_RXOIR_BIT) {
finished = true;
break;
}

if (dev_data->dummy_bytes == 0 ||
Expand All @@ -364,7 +381,11 @@
if (finished) {
set_imr(dev, 0);

#if defined(CONFIG_MULTITHREADING)
k_sem_give(&dev_data->finished);
#else
dev_data->finished = true;
#endif
}
}

Expand Down Expand Up @@ -816,8 +837,17 @@
int rc;

if (dev_id != dev_data->dev_id) {
#if defined(CONFIG_MULTITHREADING)
rc = k_sem_take(&dev_data->cfg_lock,
K_MSEC(CONFIG_MSPI_COMPLETION_TIMEOUT_TOLERANCE));
#else
if (dev_data->cfg_lock) {
rc = -1;
} else {
dev_data->cfg_lock = true;
rc = 0;
}
#endif
if (rc < 0) {
LOG_ERR("Failed to switch controller to device");
return -EBUSY;
Expand All @@ -831,15 +861,23 @@
return 0;
}

#if defined(CONFIG_MULTITHREADING)
(void)k_sem_take(&dev_data->ctx_lock, K_FOREVER);
#endif

rc = _api_dev_config(dev, param_mask, cfg);

#if defined(CONFIG_MULTITHREADING)
k_sem_give(&dev_data->ctx_lock);
#endif

if (rc < 0) {
dev_data->dev_id = NULL;
#if defined(CONFIG_MULTITHREADING)
k_sem_give(&dev_data->cfg_lock);
#else
dev_data->cfg_lock = false;
#endif
}

return rc;
Expand All @@ -851,12 +889,17 @@

struct mspi_dw_data *dev_data = dev->data;

#if defined(CONFIG_MULTITHREADING)
(void)k_sem_take(&dev_data->ctx_lock, K_FOREVER);
#endif

dev_data->dev_id = NULL;
#if defined(CONFIG_MULTITHREADING)
k_sem_give(&dev_data->cfg_lock);

k_sem_give(&dev_data->ctx_lock);
#else
dev_data->cfg_lock = false;
#endif

return 0;
}
Expand Down Expand Up @@ -1119,7 +1162,17 @@
/* Write SER to start transfer */
write_ser(dev, BIT(dev_data->dev_id->dev_idx));

#if defined(CONFIG_MULTITHREADING)
rc = k_sem_take(&dev_data->finished, timeout);
#else
if (!WAIT_FOR(dev_data->finished,
dev_data->xfer.timeout * USEC_PER_MSEC,
NULL)) {
rc = -ETIMEDOUT;

Check notice on line 1171 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:1171 - if (!WAIT_FOR(dev_data->finished, - dev_data->xfer.timeout * USEC_PER_MSEC, - NULL)) { + if (!WAIT_FOR(dev_data->finished, dev_data->xfer.timeout * USEC_PER_MSEC, NULL)) {

Check notice on line 1171 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:1171 - if (!WAIT_FOR(dev_data->finished, - dev_data->xfer.timeout * USEC_PER_MSEC, - NULL)) { + if (!WAIT_FOR(dev_data->finished, dev_data->xfer.timeout * USEC_PER_MSEC, NULL)) {
}

dev_data->finished = false;
#endif
if (read_risr(dev) & RISR_RXOIR_BIT) {
LOG_ERR("RX FIFO overflow occurred");
rc = -EIO;
Expand Down Expand Up @@ -1232,15 +1285,19 @@
return rc;
}

#if defined(CONFIG_MULTITHREADING)
(void)k_sem_take(&dev_data->ctx_lock, K_FOREVER);
#endif

if (dev_data->suspended) {
rc = -EFAULT;
} else {
rc = _api_transceive(dev, req);
}

#if defined(CONFIG_MULTITHREADING)
k_sem_give(&dev_data->ctx_lock);
#endif

rc2 = pm_device_runtime_put(dev);
if (rc2 < 0) {
Expand Down Expand Up @@ -1391,15 +1448,19 @@
return rc;
}

#if defined(CONFIG_MULTITHREADING)
(void)k_sem_take(&dev_data->ctx_lock, K_FOREVER);
#endif

if (dev_data->suspended) {
rc = -EFAULT;
} else {
rc = _api_xip_config(dev, dev_id, cfg);
}

#if defined(CONFIG_MULTITHREADING)
k_sem_give(&dev_data->ctx_lock);
#endif

rc2 = pm_device_runtime_put(dev);
if (rc2 < 0) {
Expand Down Expand Up @@ -1450,8 +1511,12 @@
return rc;
}
#endif
#if defined(CONFIG_MULTITHREADING)
if (xip_enabled ||
k_sem_take(&dev_data->ctx_lock, K_NO_WAIT) != 0) {
#else
if (xip_enabled) {
#endif
LOG_ERR("Controller in use, cannot be suspended");
return -EBUSY;
}
Expand All @@ -1460,7 +1525,9 @@

vendor_specific_suspend(dev);

#if defined(CONFIG_MULTITHREADING)
k_sem_give(&dev_data->ctx_lock);
#endif

return 0;
}
Expand All @@ -1470,7 +1537,6 @@

static int dev_init(const struct device *dev)
{
struct mspi_dw_data *dev_data = dev->data;
const struct mspi_dw_config *dev_config = dev->config;
const struct gpio_dt_spec *ce_gpio;
int rc;
Expand All @@ -1481,9 +1547,13 @@

dev_config->irq_config();

#if defined(CONFIG_MULTITHREADING)
struct mspi_dw_data *dev_data = dev->data;

k_sem_init(&dev_data->finished, 0, 1);
k_sem_init(&dev_data->cfg_lock, 1, 1);
k_sem_init(&dev_data->ctx_lock, 1, 1);
#endif

#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE)
dev_data->dev = dev;
Expand Down
1 change: 1 addition & 0 deletions drivers/power_domain/Kconfig.nrfs_gdpwr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
config POWER_DOMAIN_NRFS_GDPWR
bool "NRFS Global Domain Power Request driver"
depends on DT_HAS_NORDIC_NRFS_GDPWR_ENABLED
depends on MULTITHREADING
select NRFS
select NRFS_GDPWR_SERVICE_ENABLED
default y
Expand Down
6 changes: 6 additions & 0 deletions tests/drivers/mspi/flash/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@ tests:
- nrf54h20dk/nrf54h20/cpuapp
extra_configs:
- CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE=y
drivers.mspi.flash.mspi_nor_no_multithreading:
filter: dt_alias_exists("mspi0") and CONFIG_FLASH_MSPI_NOR
integration_platforms:
- nrf54h20dk/nrf54h20/cpuapp
extra_configs:
- CONFIG_MULTITHREADING=n
Loading