Skip to content
27 changes: 17 additions & 10 deletions drivers/flash/flash_mspi_nor.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,15 +567,20 @@
enum mspi_io_mode io_mode = dev_config->mspi_nor_cfg.io_mode;
int rc = 0;

/* For Quad 1-1-4 and 1-4-4, entering or leaving mode is defined in JEDEC216 BFP DW15 QER */
if (io_mode == MSPI_IO_MODE_SINGLE) {
rc = quad_enable_set(dev, false);
} else if ((io_mode == MSPI_IO_MODE_QUAD_1_1_4) || (io_mode == MSPI_IO_MODE_QUAD_1_4_4)) {
rc = quad_enable_set(dev, true);
}
if (dev_config->dw15_qer != JESD216_DW15_QER_VAL_NONE) {
/* For Quad 1-1-4 and 1-4-4, entering or leaving mode is defined
* in JEDEC216 BFP DW15 QER
*/
if (io_mode == MSPI_IO_MODE_SINGLE) {
rc = quad_enable_set(dev, false);
} else if (io_mode == MSPI_IO_MODE_QUAD_1_1_4 ||
io_mode == MSPI_IO_MODE_QUAD_1_4_4) {
rc = quad_enable_set(dev, true);
}

if (rc < 0) {
LOG_ERR("Failed to modify Quad Enable bit: %d", rc);
if (rc < 0) {
LOG_ERR("Failed to modify Quad Enable bit: %d", rc);
}
}

if ((dev_config->quirks != NULL) && (dev_config->quirks->post_switch_mode != NULL)) {
Expand Down Expand Up @@ -646,8 +651,10 @@
/* Some chips reuse RESET pin for data in Quad modes:
* force single line mode before resetting.
*/
if ((io_mode == MSPI_IO_MODE_SINGLE) || (io_mode == MSPI_IO_MODE_QUAD_1_1_4) ||
(io_mode == MSPI_IO_MODE_QUAD_1_4_4)) {
if (dev_config->dw15_qer != JESD216_DW15_QER_VAL_NONE &&
(io_mode == MSPI_IO_MODE_SINGLE ||
io_mode == MSPI_IO_MODE_QUAD_1_1_4 ||
io_mode == MSPI_IO_MODE_QUAD_1_4_4)) {

Check notice on line 657 in drivers/flash/flash_mspi_nor.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/flash/flash_mspi_nor.c:657 - (io_mode == MSPI_IO_MODE_SINGLE || - io_mode == MSPI_IO_MODE_QUAD_1_1_4 || + (io_mode == MSPI_IO_MODE_SINGLE || io_mode == MSPI_IO_MODE_QUAD_1_1_4 ||
rc = quad_enable_set(dev, false);

if (rc < 0) {
Expand Down
65 changes: 42 additions & 23 deletions drivers/flash/nrf_qspi_nor.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ struct qspi_nor_data {
*/
volatile bool ready;
#endif /* CONFIG_MULTITHREADING */
bool xip_enabled;
uint32_t xip_users;
};

struct qspi_nor_config {
Expand Down Expand Up @@ -313,7 +313,7 @@ static void qspi_acquire(const struct device *dev)

qspi_lock(dev);

if (!dev_data->xip_enabled) {
if (dev_data->xip_users == 0) {
qspi_clock_div_change();

pm_device_busy_set(dev);
Expand All @@ -331,7 +331,7 @@ static void qspi_release(const struct device *dev)
deactivate = atomic_dec(&dev_data->usage_count) == 1;
#endif

if (!dev_data->xip_enabled) {
if (dev_data->xip_users == 0) {
qspi_clock_div_restore();

if (deactivate) {
Expand Down Expand Up @@ -1344,35 +1344,54 @@ static int qspi_nor_pm_action(const struct device *dev,
}
#endif /* CONFIG_PM_DEVICE */

static void on_xip_enable(const struct device *dev)
{
#if NRF_QSPI_HAS_XIPEN
nrf_qspi_xip_set(NRF_QSPI, true);
#endif
(void)nrfx_qspi_activate(false);
}

static void on_xip_disable(const struct device *dev)
{
/* It turns out that when the QSPI peripheral is deactivated
* after a XIP transaction, it cannot be later successfully
* reactivated and an attempt to perform another XIP transaction
* results in the CPU being hung; even a debug session cannot be
* started then and the SoC has to be recovered.
* As a workaround, at least until the cause of such behavior
* is fully clarified, perform a simple non-XIP transaction
* (a read of the status register) before deactivating the QSPI.
* This prevents the issue from occurring.
*/
(void)qspi_rdsr(dev, 1);

#if NRF_QSPI_HAS_XIPEN
nrf_qspi_xip_set(NRF_QSPI, false);
#endif
}

void z_impl_nrf_qspi_nor_xip_enable(const struct device *dev, bool enable)
{
struct qspi_nor_data *dev_data = dev->data;

if (dev_data->xip_enabled == enable) {
return;
}

qspi_acquire(dev);

#if NRF_QSPI_HAS_XIPEN
nrf_qspi_xip_set(NRF_QSPI, enable);
#endif
if (enable) {
(void)nrfx_qspi_activate(false);
if (dev_data->xip_users == 0) {
on_xip_enable(dev);
}

++dev_data->xip_users;
} else if (dev_data->xip_users == 0) {
LOG_ERR("Unbalanced XIP disabling");
} else {
/* It turns out that when the QSPI peripheral is deactivated
* after a XIP transaction, it cannot be later successfully
* reactivated and an attempt to perform another XIP transaction
* results in the CPU being hung; even a debug session cannot be
* started then and the SoC has to be recovered.
* As a workaround, at least until the cause of such behavior
* is fully clarified, perform a simple non-XIP transaction
* (a read of the status register) before deactivating the QSPI.
* This prevents the issue from occurring.
*/
(void)qspi_rdsr(dev, 1);
--dev_data->xip_users;

if (dev_data->xip_users == 0) {
on_xip_disable(dev);
}
}
dev_data->xip_enabled = enable;

qspi_release(dev);
}
Expand Down
Loading
Loading