drivers: spi: nrfx_spim: Add support for device runtime PM
Enable the device runtime power management on the SPIM shim. Signed-off-by: Adam Kondraciuk <adam.kondraciuk@nordicsemi.no> Signed-off-by: Nikodem Kastelik <nikodem.kastelik@nordicsemi.no>
This commit is contained in:
parent
1a931d33d6
commit
e8a327329a
1 changed files with 41 additions and 42 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include <zephyr/drivers/spi/rtio.h>
|
#include <zephyr/drivers/spi/rtio.h>
|
||||||
#include <zephyr/cache.h>
|
#include <zephyr/cache.h>
|
||||||
#include <zephyr/pm/device.h>
|
#include <zephyr/pm/device.h>
|
||||||
|
#include <zephyr/pm/device_runtime.h>
|
||||||
#include <zephyr/drivers/pinctrl.h>
|
#include <zephyr/drivers/pinctrl.h>
|
||||||
#include <zephyr/mem_mgmt/mem_attr.h>
|
#include <zephyr/mem_mgmt/mem_attr.h>
|
||||||
#include <soc.h>
|
#include <soc.h>
|
||||||
|
@ -90,6 +91,8 @@ static inline void finalize_spi_transaction(const struct device *dev, bool deact
|
||||||
if (NRF_SPIM_IS_320MHZ_SPIM(reg) && !(dev_data->ctx.config->operation & SPI_HOLD_ON_CS)) {
|
if (NRF_SPIM_IS_320MHZ_SPIM(reg) && !(dev_data->ctx.config->operation & SPI_HOLD_ON_CS)) {
|
||||||
nrfy_spim_disable(reg);
|
nrfy_spim_disable(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pm_device_runtime_put_async(dev, K_NO_WAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t get_nrf_spim_frequency(uint32_t frequency)
|
static inline uint32_t get_nrf_spim_frequency(uint32_t frequency)
|
||||||
|
@ -460,6 +463,7 @@ static int transceive(const struct device *dev,
|
||||||
void *reg = dev_config->spim.p_reg;
|
void *reg = dev_config->spim.p_reg;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
pm_device_runtime_get(dev);
|
||||||
spi_context_lock(&dev_data->ctx, asynchronous, cb, userdata, spi_cfg);
|
spi_context_lock(&dev_data->ctx, asynchronous, cb, userdata, spi_cfg);
|
||||||
|
|
||||||
error = configure(dev, spi_cfg);
|
error = configure(dev, spi_cfg);
|
||||||
|
@ -571,56 +575,49 @@ static DEVICE_API(spi, spi_nrfx_driver_api) = {
|
||||||
.release = spi_nrfx_release,
|
.release = spi_nrfx_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_PM_DEVICE
|
static void spim_resume(const struct device *dev)
|
||||||
static int spim_nrfx_pm_action(const struct device *dev,
|
|
||||||
enum pm_device_action action)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
|
||||||
struct spi_nrfx_data *dev_data = dev->data;
|
|
||||||
const struct spi_nrfx_config *dev_config = dev->config;
|
const struct spi_nrfx_config *dev_config = dev->config;
|
||||||
|
|
||||||
switch (action) {
|
(void)pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_DEFAULT);
|
||||||
case PM_DEVICE_ACTION_RESUME:
|
/* nrfx_spim_init() will be called at configuration before
|
||||||
ret = pinctrl_apply_state(dev_config->pcfg,
|
* the next transfer.
|
||||||
PINCTRL_STATE_DEFAULT);
|
*/
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
/* nrfx_spim_init() will be called at configuration before
|
|
||||||
* the next transfer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef CONFIG_SOC_NRF54H20_GPD
|
#ifdef CONFIG_SOC_NRF54H20_GPD
|
||||||
nrf_gpd_retain_pins_set(dev_config->pcfg, false);
|
nrf_gpd_retain_pins_set(dev_config->pcfg, false);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
static void spim_suspend(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct spi_nrfx_config *dev_config = dev->config;
|
||||||
|
struct spi_nrfx_data *dev_data = dev->data;
|
||||||
|
|
||||||
case PM_DEVICE_ACTION_SUSPEND:
|
if (dev_data->initialized) {
|
||||||
if (dev_data->initialized) {
|
nrfx_spim_uninit(&dev_config->spim);
|
||||||
nrfx_spim_uninit(&dev_config->spim);
|
dev_data->initialized = false;
|
||||||
dev_data->initialized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_SOC_NRF54H20_GPD
|
|
||||||
nrf_gpd_retain_pins_set(dev_config->pcfg, true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = pinctrl_apply_state(dev_config->pcfg,
|
|
||||||
PINCTRL_STATE_SLEEP);
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ret = -ENOTSUP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
#ifdef CONFIG_SOC_NRF54H20_GPD
|
||||||
}
|
nrf_gpd_retain_pins_set(dev_config->pcfg, true);
|
||||||
#endif /* CONFIG_PM_DEVICE */
|
#endif
|
||||||
|
|
||||||
|
(void)pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_SLEEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int spim_nrfx_pm_action(const struct device *dev, enum pm_device_action action)
|
||||||
|
{
|
||||||
|
if (action == PM_DEVICE_ACTION_RESUME) {
|
||||||
|
spim_resume(dev);
|
||||||
|
} else if (IS_ENABLED(CONFIG_PM_DEVICE) && (action == PM_DEVICE_ACTION_SUSPEND)) {
|
||||||
|
spim_suspend(dev);
|
||||||
|
} else {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int spi_nrfx_init(const struct device *dev)
|
static int spi_nrfx_init(const struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -655,10 +652,12 @@ static int spi_nrfx_init(const struct device *dev)
|
||||||
spi_context_unlock_unconditionally(&dev_data->ctx);
|
spi_context_unlock_unconditionally(&dev_data->ctx);
|
||||||
|
|
||||||
#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
|
#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
|
||||||
return anomaly_58_workaround_init(dev);
|
err = anomaly_58_workaround_init(dev);
|
||||||
#else
|
if (err < 0) {
|
||||||
return 0;
|
return err;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return pm_device_driver_init(dev, spim_nrfx_pm_action);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* We use NODELABEL here because the nrfx API requires us to call
|
* We use NODELABEL here because the nrfx API requires us to call
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue