@@ -41,7 +41,7 @@ struct qspi_nor_data {
41
41
*/
42
42
volatile bool ready ;
43
43
#endif /* CONFIG_MULTITHREADING */
44
- bool xip_enabled ;
44
+ uint32_t xip_users ;
45
45
};
46
46
47
47
struct qspi_nor_config {
@@ -313,7 +313,7 @@ static void qspi_acquire(const struct device *dev)
313
313
314
314
qspi_lock (dev );
315
315
316
- if (! dev_data -> xip_enabled ) {
316
+ if (dev_data -> xip_users == 0 ) {
317
317
qspi_clock_div_change ();
318
318
319
319
pm_device_busy_set (dev );
@@ -331,7 +331,7 @@ static void qspi_release(const struct device *dev)
331
331
deactivate = atomic_dec (& dev_data -> usage_count ) == 1 ;
332
332
#endif
333
333
334
- if (! dev_data -> xip_enabled ) {
334
+ if (dev_data -> xip_users == 0 ) {
335
335
qspi_clock_div_restore ();
336
336
337
337
if (deactivate ) {
@@ -1344,35 +1344,54 @@ static int qspi_nor_pm_action(const struct device *dev,
1344
1344
}
1345
1345
#endif /* CONFIG_PM_DEVICE */
1346
1346
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
+
1347
1374
void z_impl_nrf_qspi_nor_xip_enable (const struct device * dev , bool enable )
1348
1375
{
1349
1376
struct qspi_nor_data * dev_data = dev -> data ;
1350
1377
1351
- if (dev_data -> xip_enabled == enable ) {
1352
- return ;
1353
- }
1354
-
1355
1378
qspi_acquire (dev );
1356
1379
1357
- #if NRF_QSPI_HAS_XIPEN
1358
- nrf_qspi_xip_set (NRF_QSPI , enable );
1359
- #endif
1360
1380
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" );
1362
1388
} 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
+ }
1374
1394
}
1375
- dev_data -> xip_enabled = enable ;
1376
1395
1377
1396
qspi_release (dev );
1378
1397
}
0 commit comments