@@ -41,7 +41,7 @@ struct qspi_nor_data {
4141 */
4242 volatile bool ready ;
4343#endif /* CONFIG_MULTITHREADING */
44- bool xip_enabled ;
44+ uint32_t xip_users ;
4545};
4646
4747struct qspi_nor_config {
@@ -313,7 +313,7 @@ static void qspi_acquire(const struct device *dev)
313313
314314 qspi_lock (dev );
315315
316- if (! dev_data -> xip_enabled ) {
316+ if (dev_data -> xip_users == 0 ) {
317317 qspi_clock_div_change ();
318318
319319 pm_device_busy_set (dev );
@@ -331,7 +331,7 @@ static void qspi_release(const struct device *dev)
331331 deactivate = atomic_dec (& dev_data -> usage_count ) == 1 ;
332332#endif
333333
334- if (! dev_data -> xip_enabled ) {
334+ if (dev_data -> xip_users == 0 ) {
335335 qspi_clock_div_restore ();
336336
337337 if (deactivate ) {
@@ -1344,35 +1344,54 @@ static int qspi_nor_pm_action(const struct device *dev,
13441344}
13451345#endif /* CONFIG_PM_DEVICE */
13461346
1347+ static void on_xip_enable (const struct device * dev )
1348+ {
1349+ #if NRF_QSPI_HAS_XIPEN
1350+ nrf_qspi_xip_set (NRF_QSPI , true);
1351+ #endif
1352+ (void )nrfx_qspi_activate (false);
1353+ }
1354+
1355+ static void on_xip_disable (const struct device * dev )
1356+ {
1357+ /* It turns out that when the QSPI peripheral is deactivated
1358+ * after a XIP transaction, it cannot be later successfully
1359+ * reactivated and an attempt to perform another XIP transaction
1360+ * results in the CPU being hung; even a debug session cannot be
1361+ * started then and the SoC has to be recovered.
1362+ * As a workaround, at least until the cause of such behavior
1363+ * is fully clarified, perform a simple non-XIP transaction
1364+ * (a read of the status register) before deactivating the QSPI.
1365+ * This prevents the issue from occurring.
1366+ */
1367+ (void )qspi_rdsr (dev , 1 );
1368+
1369+ #if NRF_QSPI_HAS_XIPEN
1370+ nrf_qspi_xip_set (NRF_QSPI , false);
1371+ #endif
1372+ }
1373+
13471374void z_impl_nrf_qspi_nor_xip_enable (const struct device * dev , bool enable )
13481375{
13491376 struct qspi_nor_data * dev_data = dev -> data ;
13501377
1351- if (dev_data -> xip_enabled == enable ) {
1352- return ;
1353- }
1354-
13551378 qspi_acquire (dev );
13561379
1357- #if NRF_QSPI_HAS_XIPEN
1358- nrf_qspi_xip_set (NRF_QSPI , enable );
1359- #endif
13601380 if (enable ) {
1361- (void )nrfx_qspi_activate (false);
1381+ if (dev_data -> xip_users == 0 ) {
1382+ on_xip_enable (dev );
1383+ }
1384+
1385+ ++ dev_data -> xip_users ;
1386+ } else if (dev_data -> xip_users == 0 ) {
1387+ LOG_ERR ("Unbalanced XIP disabling" );
13621388 } else {
1363- /* It turns out that when the QSPI peripheral is deactivated
1364- * after a XIP transaction, it cannot be later successfully
1365- * reactivated and an attempt to perform another XIP transaction
1366- * results in the CPU being hung; even a debug session cannot be
1367- * started then and the SoC has to be recovered.
1368- * As a workaround, at least until the cause of such behavior
1369- * is fully clarified, perform a simple non-XIP transaction
1370- * (a read of the status register) before deactivating the QSPI.
1371- * This prevents the issue from occurring.
1372- */
1373- (void )qspi_rdsr (dev , 1 );
1389+ -- dev_data -> xip_users ;
1390+
1391+ if (dev_data -> xip_users == 0 ) {
1392+ on_xip_disable (dev );
1393+ }
13741394 }
1375- dev_data -> xip_enabled = enable ;
13761395
13771396 qspi_release (dev );
13781397}
0 commit comments