diff --git a/drivers/spi/spi_cc23x0.c b/drivers/spi/spi_cc23x0.c index fb235dedcdc1..108c6aae1d5d 100644 --- a/drivers/spi/spi_cc23x0.c +++ b/drivers/spi/spi_cc23x0.c @@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(spi_cc23x0, CONFIG_SPI_LOG_LEVEL); #include #include #include +#include +#include +#include #include #include @@ -63,6 +66,22 @@ struct spi_cc23x0_data { #endif }; +static inline void spi_cc23x0_pm_policy_state_lock_get(void) +{ +#ifdef CONFIG_PM_DEVICE + pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); +#endif +} + +static inline void spi_cc23x0_pm_policy_state_lock_put(void) +{ +#ifdef CONFIG_PM_DEVICE + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); +#endif +} + static void spi_cc23x0_isr(const struct device *dev) { const struct spi_cc23x0_config *cfg = dev->config; @@ -307,6 +326,8 @@ static int spi_cc23x0_transceive(const struct device *dev, }; #endif + spi_cc23x0_pm_policy_state_lock_get(); + spi_context_lock(ctx, false, NULL, NULL, config); ret = spi_cc23x0_configure(dev, config); @@ -339,16 +360,22 @@ static int spi_cc23x0_transceive(const struct device *dev, block_cfg_rx.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT; block_cfg_rx.block_size = SPI_CC23_DFS * data->tx_len_left; - ret = dma_config(cfg->dma_dev, cfg->dma_channel_tx, &dma_cfg_tx); + ret = pm_device_runtime_get(cfg->dma_dev); if (ret) { - LOG_ERR("Failed to configure DMA TX channel"); + LOG_ERR("Failed to resume DMA (%d)", ret); goto int_disable; } + ret = dma_config(cfg->dma_dev, cfg->dma_channel_tx, &dma_cfg_tx); + if (ret) { + LOG_ERR("Failed to configure DMA TX channel (%d)", ret); + goto dma_suspend; + } + ret = dma_config(cfg->dma_dev, cfg->dma_channel_rx, &dma_cfg_rx); if (ret) { - LOG_ERR("Failed to configure DMA RX channel"); - goto int_disable; + LOG_ERR("Failed to configure DMA RX channel (%d)", ret); + goto dma_suspend; } /* Disable DMA triggers */ @@ -364,7 +391,7 @@ static int spi_cc23x0_transceive(const struct device *dev, ret = spi_context_wait_for_completion(&data->ctx); if (ret) { LOG_ERR("SPI transfer failed (%d)", ret); - goto int_disable; + goto dma_suspend; } spi_context_update_tx(ctx, SPI_CC23_DFS, data->tx_len_left); @@ -372,6 +399,11 @@ static int spi_cc23x0_transceive(const struct device *dev, LOG_DBG("SPI transfer completed"); +dma_suspend: + ret = pm_device_runtime_put(cfg->dma_dev); + if (ret) { + LOG_ERR("Failed to suspend DMA (%d)", ret); + } int_disable: SPIDisableInt(cfg->base, SPI_CC23_INT_MASK); #else @@ -388,6 +420,7 @@ static int spi_cc23x0_transceive(const struct device *dev, ctx_release: spi_context_release(ctx, ret); + spi_cc23x0_pm_policy_state_lock_put(); return ret; } @@ -434,6 +467,12 @@ static int spi_cc23x0_init(const struct device *dev) LOG_ERR("DMA not ready"); return -ENODEV; } + + ret = pm_device_runtime_enable(cfg->dma_dev); + if (ret) { + LOG_ERR("Failed to enable DMA runtime PM"); + return ret; + } #endif ret = spi_context_cs_configure_all(&data->ctx); @@ -446,6 +485,29 @@ static int spi_cc23x0_init(const struct device *dev) return 0; } +#ifdef CONFIG_PM_DEVICE + +static int spi_cc23x0_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct spi_cc23x0_config *cfg = dev->config; + struct spi_cc23x0_data *data = dev->data; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + SPIDisable(cfg->base); + CLKCTLDisable(CLKCTL_BASE, CLKCTL_SPI0); + return 0; + case PM_DEVICE_ACTION_RESUME: + /* Force SPI to be reconfigured at next transfer */ + data->ctx.config = NULL; + return 0; + default: + return -ENOTSUP; + } +} + +#endif /* CONFIG_PM_DEVICE */ + #ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN #define SPI_CC23X0_DMA_INIT(n) \ .dma_dev = DEVICE_DT_GET(TI_CC23X0_DT_INST_DMA_CTLR(n, tx)), \ @@ -459,6 +521,7 @@ static int spi_cc23x0_init(const struct device *dev) #define SPI_CC23X0_INIT(n) \ PINCTRL_DT_INST_DEFINE(n); \ + PM_DEVICE_DT_INST_DEFINE(n, spi_cc23x0_pm_action); \ \ static void spi_irq_config_func_##n(void) \ { \ @@ -484,7 +547,7 @@ static int spi_cc23x0_init(const struct device *dev) \ DEVICE_DT_INST_DEFINE(n, \ spi_cc23x0_init, \ - NULL, \ + PM_DEVICE_DT_INST_GET(n), \ &spi_cc23x0_data_##n, \ &spi_cc23x0_config_##n, \ POST_KERNEL, \