Skip to content

Commit 1bb44da

Browse files
committed
drivers: spi: cc23x0: Add power management
Add PM support to cc23x0 SPI module. Signed-off-by: Julien Panis <jpanis@baylibre.com>
1 parent ba905d0 commit 1bb44da

File tree

1 file changed

+69
-6
lines changed

1 file changed

+69
-6
lines changed

drivers/spi/spi_cc23x0.c

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(spi_cc23x0, CONFIG_SPI_LOG_LEVEL);
1414
#include <zephyr/drivers/pinctrl.h>
1515
#include <zephyr/drivers/spi.h>
1616
#include <zephyr/irq.h>
17+
#include <zephyr/pm/device.h>
18+
#include <zephyr/pm/device_runtime.h>
19+
#include <zephyr/pm/policy.h>
1720
#include <zephyr/sys/util.h>
1821

1922
#include <driverlib/clkctl.h>
@@ -63,6 +66,22 @@ struct spi_cc23x0_data {
6366
#endif
6467
};
6568

69+
static inline void spi_cc23x0_pm_policy_state_lock_get(void)
70+
{
71+
#ifdef CONFIG_PM_DEVICE
72+
pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES);
73+
pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
74+
#endif
75+
}
76+
77+
static inline void spi_cc23x0_pm_policy_state_lock_put(void)
78+
{
79+
#ifdef CONFIG_PM_DEVICE
80+
pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
81+
pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES);
82+
#endif
83+
}
84+
6685
static void spi_cc23x0_isr(const struct device *dev)
6786
{
6887
const struct spi_cc23x0_config *cfg = dev->config;
@@ -307,6 +326,8 @@ static int spi_cc23x0_transceive(const struct device *dev,
307326
};
308327
#endif
309328

329+
spi_cc23x0_pm_policy_state_lock_get();
330+
310331
spi_context_lock(ctx, false, NULL, NULL, config);
311332

312333
ret = spi_cc23x0_configure(dev, config);
@@ -339,16 +360,22 @@ static int spi_cc23x0_transceive(const struct device *dev,
339360
block_cfg_rx.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT;
340361
block_cfg_rx.block_size = SPI_CC23_DFS * data->tx_len_left;
341362

342-
ret = dma_config(cfg->dma_dev, cfg->dma_channel_tx, &dma_cfg_tx);
363+
ret = pm_device_runtime_get(cfg->dma_dev);
343364
if (ret) {
344-
LOG_ERR("Failed to configure DMA TX channel");
365+
LOG_ERR("Failed to resume DMA (%d)", ret);
345366
goto int_disable;
346367
}
347368

369+
ret = dma_config(cfg->dma_dev, cfg->dma_channel_tx, &dma_cfg_tx);
370+
if (ret) {
371+
LOG_ERR("Failed to configure DMA TX channel (%d)", ret);
372+
goto dma_suspend;
373+
}
374+
348375
ret = dma_config(cfg->dma_dev, cfg->dma_channel_rx, &dma_cfg_rx);
349376
if (ret) {
350-
LOG_ERR("Failed to configure DMA RX channel");
351-
goto int_disable;
377+
LOG_ERR("Failed to configure DMA RX channel (%d)", ret);
378+
goto dma_suspend;
352379
}
353380

354381
/* Disable DMA triggers */
@@ -364,14 +391,19 @@ static int spi_cc23x0_transceive(const struct device *dev,
364391
ret = spi_context_wait_for_completion(&data->ctx);
365392
if (ret) {
366393
LOG_ERR("SPI transfer failed (%d)", ret);
367-
goto int_disable;
394+
goto dma_suspend;
368395
}
369396

370397
spi_context_update_tx(ctx, SPI_CC23_DFS, data->tx_len_left);
371398
spi_context_update_rx(ctx, SPI_CC23_DFS, data->tx_len_left);
372399

373400
LOG_DBG("SPI transfer completed");
374401

402+
dma_suspend:
403+
ret = pm_device_runtime_put(cfg->dma_dev);
404+
if (ret) {
405+
LOG_ERR("Failed to suspend DMA (%d)", ret);
406+
}
375407
int_disable:
376408
SPIDisableInt(cfg->base, SPI_CC23_INT_MASK);
377409
#else
@@ -388,6 +420,7 @@ static int spi_cc23x0_transceive(const struct device *dev,
388420

389421
ctx_release:
390422
spi_context_release(ctx, ret);
423+
spi_cc23x0_pm_policy_state_lock_put();
391424
return ret;
392425
}
393426

@@ -434,6 +467,12 @@ static int spi_cc23x0_init(const struct device *dev)
434467
LOG_ERR("DMA not ready");
435468
return -ENODEV;
436469
}
470+
471+
ret = pm_device_runtime_enable(cfg->dma_dev);
472+
if (ret) {
473+
LOG_ERR("Failed to enable DMA runtime PM");
474+
return ret;
475+
}
437476
#endif
438477

439478
ret = spi_context_cs_configure_all(&data->ctx);
@@ -446,6 +485,29 @@ static int spi_cc23x0_init(const struct device *dev)
446485
return 0;
447486
}
448487

488+
#ifdef CONFIG_PM_DEVICE
489+
490+
static int spi_cc23x0_pm_action(const struct device *dev, enum pm_device_action action)
491+
{
492+
const struct spi_cc23x0_config *cfg = dev->config;
493+
struct spi_cc23x0_data *data = dev->data;
494+
495+
switch (action) {
496+
case PM_DEVICE_ACTION_SUSPEND:
497+
SPIDisable(cfg->base);
498+
CLKCTLDisable(CLKCTL_BASE, CLKCTL_SPI0);
499+
return 0;
500+
case PM_DEVICE_ACTION_RESUME:
501+
/* Force SPI to be reconfigured at next transfer */
502+
data->ctx.config = NULL;
503+
return 0;
504+
default:
505+
return -ENOTSUP;
506+
}
507+
}
508+
509+
#endif /* CONFIG_PM_DEVICE */
510+
449511
#ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
450512
#define SPI_CC23X0_DMA_INIT(n) \
451513
.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)
459521

460522
#define SPI_CC23X0_INIT(n) \
461523
PINCTRL_DT_INST_DEFINE(n); \
524+
PM_DEVICE_DT_INST_DEFINE(n, spi_cc23x0_pm_action); \
462525
\
463526
static void spi_irq_config_func_##n(void) \
464527
{ \
@@ -484,7 +547,7 @@ static int spi_cc23x0_init(const struct device *dev)
484547
\
485548
DEVICE_DT_INST_DEFINE(n, \
486549
spi_cc23x0_init, \
487-
NULL, \
550+
PM_DEVICE_DT_INST_GET(n), \
488551
&spi_cc23x0_data_##n, \
489552
&spi_cc23x0_config_##n, \
490553
POST_KERNEL, \

0 commit comments

Comments
 (0)