diff --git a/drivers/i2c/i2c_nrfx_twim.c b/drivers/i2c/i2c_nrfx_twim.c index e3c307231ab..bc26bf84112 100644 --- a/drivers/i2c/i2c_nrfx_twim.c +++ b/drivers/i2c/i2c_nrfx_twim.c @@ -285,7 +285,7 @@ static DEVICE_API(i2c, i2c_nrfx_twim_driver_api) = { DT_PROP(I2C(idx), easydma_maxcnt_bits)), \ }; \ PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action, \ - PM_DEVICE_ISR_SAFE); \ + I2C_PM_ISR_SAFE(idx)); \ I2C_DEVICE_DT_DEINIT_DEFINE(I2C(idx), \ i2c_nrfx_twim_init, \ i2c_nrfx_twim_deinit, \ diff --git a/drivers/i2c/i2c_nrfx_twim_common.h b/drivers/i2c/i2c_nrfx_twim_common.h index 3c5c82311ba..d476ba3f05f 100644 --- a/drivers/i2c/i2c_nrfx_twim_common.h +++ b/drivers/i2c/i2c_nrfx_twim_common.h @@ -31,6 +31,26 @@ extern "C" { #define I2C_FREQUENCY(idx) I2C_NRFX_TWIM_FREQUENCY(DT_PROP_OR(I2C(idx), clock_frequency, \ I2C_BITRATE_STANDARD)) +/* Macro determines PM actions interrupt safety level. + * + * Requesting/releasing TWIM device may be ISR safe, but it cannot be reliably known whether + * managing its power domain is. It is then assumed that if power domains are used, device is + * no longer ISR safe. This macro let's us check if we will be requesting/releasing + * power domains and determines PM device ISR safety value. + */ +#define I2C_PM_ISR_SAFE(idx) \ + COND_CODE_1( \ + UTIL_AND( \ + IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN), \ + UTIL_AND( \ + DT_NODE_HAS_PROP(I2C(idx), power_domains), \ + DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE(I2C(idx), power_domains)) \ + ) \ + ), \ + (0), \ + (PM_DEVICE_ISR_SAFE) \ + ) + struct i2c_nrfx_twim_common_config { nrfx_twim_t twim; nrfx_twim_config_t twim_config; diff --git a/drivers/i2c/i2c_nrfx_twim_rtio.c b/drivers/i2c/i2c_nrfx_twim_rtio.c index 0ddf5ffdd77..7326deaafb0 100644 --- a/drivers/i2c/i2c_nrfx_twim_rtio.c +++ b/drivers/i2c/i2c_nrfx_twim_rtio.c @@ -287,7 +287,7 @@ static int i2c_nrfx_twim_rtio_deinit(const struct device *dev) }, \ .ctx = &_i2c##idx##_twim_rtio, \ }; \ - PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action, PM_DEVICE_ISR_SAFE); \ + PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action, I2C_PM_ISR_SAFE(idx)); \ I2C_DEVICE_DT_DEINIT_DEFINE(I2C(idx), i2c_nrfx_twim_rtio_init, i2c_nrfx_twim_rtio_deinit, \ PM_DEVICE_DT_GET(I2C(idx)), &twim_##idx##z_data, \ &twim_##idx##z_config, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ diff --git a/drivers/sensor/nordic/qdec_nrfx/qdec_nrfx.c b/drivers/sensor/nordic/qdec_nrfx/qdec_nrfx.c index 9ecfb5c122d..0d5eb5ab8cc 100644 --- a/drivers/sensor/nordic/qdec_nrfx/qdec_nrfx.c +++ b/drivers/sensor/nordic/qdec_nrfx/qdec_nrfx.c @@ -272,6 +272,26 @@ static int qdec_nrfx_init(const struct device *dev) #define QDEC(idx) DT_NODELABEL(qdec##idx) #define QDEC_PROP(idx, prop) DT_PROP(QDEC(idx), prop) +/* Macro determines PM actions interrupt safety level. + * + * Requesting/releasing QDEC device may be ISR safe, but it cannot be reliably known whether + * managing its power domain is. It is then assumed that if power domains are used, device is + * no longer ISR safe. This macro let's us check if we will be requesting/releasing + * power domains and determines PM device ISR safety value. + */ +#define QDEC_PM_ISR_SAFE(idx) \ + COND_CODE_1( \ + UTIL_AND( \ + IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN), \ + UTIL_AND( \ + DT_NODE_HAS_PROP(QDEC(idx), power_domains), \ + DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE(QDEC(idx), power_domains)) \ + ) \ + ), \ + (0), \ + (PM_DEVICE_ISR_SAFE) \ + ) + #define SENSOR_NRFX_QDEC_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(QDEC(idx)); \ BUILD_ASSERT(QDEC_PROP(idx, steps) > 0, \ @@ -301,7 +321,7 @@ static int qdec_nrfx_init(const struct device *dev) .enable_pin = DT_PROP_OR(QDEC(idx), enable_pin, NRF_QDEC_PIN_NOT_CONNECTED), \ .steps = QDEC_PROP(idx, steps), \ }; \ - PM_DEVICE_DT_DEFINE(QDEC(idx), qdec_nrfx_pm_action, PM_DEVICE_ISR_SAFE); \ + PM_DEVICE_DT_DEFINE(QDEC(idx), qdec_nrfx_pm_action, QDEC_PM_ISR_SAFE(idx)); \ SENSOR_DEVICE_DT_DEFINE(QDEC(idx), \ qdec_nrfx_init, \ PM_DEVICE_DT_GET(QDEC(idx)), \ diff --git a/drivers/spi/spi_nrfx_spis.c b/drivers/spi/spi_nrfx_spis.c index 64c9a6f14c4..aa59d9abc9b 100644 --- a/drivers/spi/spi_nrfx_spis.c +++ b/drivers/spi/spi_nrfx_spis.c @@ -551,6 +551,32 @@ static int spi_nrfx_init(const struct device *dev) return pm_device_driver_init(dev, spi_nrfx_pm_action); } +/* Macro determines PM actions interrupt safety level. + * + * Requesting/releasing SPIS device may be ISR safe, but it cannot be reliably known whether + * managing its power domain is. It is then assumed that if power domains are used, device is + * no longer ISR safe. This macro let's us check if we will be requesting/releasing + * power domains and determines PM device ISR safety value. + * + * Additionally, fast SPIS devices are not ISR safe. + */ +#define SPIS_PM_ISR_SAFE(idx) \ + COND_CODE_1( \ + UTIL_AND( \ + IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN), \ + UTIL_AND( \ + DT_NODE_HAS_PROP(SPIS(idx), power_domains), \ + DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE(SPIS(idx), power_domains)) \ + ) \ + ), \ + (0), \ + (COND_CODE_1( \ + SPIS_IS_FAST(idx), \ + (0), \ + (PM_DEVICE_ISR_SAFE) \ + )) \ + ) + #define SPI_NRFX_SPIS_DEFINE(idx) \ NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(SPIS(idx)); \ static void irq_connect##idx(void) \ @@ -597,8 +623,7 @@ static int spi_nrfx_init(const struct device *dev) !(DT_GPIO_FLAGS(SPIS(idx), wake_gpios) & GPIO_ACTIVE_LOW),\ "WAKE line must be configured as active high"); \ PM_DEVICE_DT_DEFINE(SPIS(idx), spi_nrfx_pm_action, \ - COND_CODE_1(SPIS_IS_FAST(idx), (0), \ - (PM_DEVICE_ISR_SAFE))); \ + SPIS_PM_ISR_SAFE(idx)); \ SPI_DEVICE_DT_DEFINE(SPIS(idx), \ spi_nrfx_init, \ PM_DEVICE_DT_GET(SPIS(idx)), \