Skip to content

drivers: crypto: cc23x0: Add power management #92221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 133 additions & 10 deletions drivers/crypto/crypto_cc23x0.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(crypto_cc23x0, CONFIG_CRYPTO_LOG_LEVEL);
#include <zephyr/drivers/dma.h>
#include <zephyr/irq.h>
#include <zephyr/kernel.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/device_runtime.h>
#include <zephyr/pm/policy.h>
#include <zephyr/sys/util.h>

#include <string.h>
Expand Down Expand Up @@ -80,6 +83,22 @@ struct crypto_cc23x0_data {
#endif
};

static inline void crypto_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 crypto_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 crypto_cc23x0_isr(const struct device *dev)
{
struct crypto_cc23x0_data *data = dev->data;
Expand All @@ -102,17 +121,42 @@ static void crypto_cc23x0_isr(const struct device *dev)
AESClearInterrupt(status);
}

static void crypto_cc23x0_cleanup(const struct device *dev)
{
#ifdef CONFIG_CRYPTO_CC23X0_DMA

static int crypto_cc23x0_dma_enable(const struct device *dev, bool *dma_enabled)
{
const struct crypto_cc23x0_config *cfg = dev->config;
int ret;

ret = pm_device_runtime_get(cfg->dma_dev);
if (ret) {
LOG_ERR("Failed to resume DMA");
*dma_enabled = false;
} else {
*dma_enabled = true;
}

return ret;
}

static void crypto_cc23x0_dma_cleanup(const struct device *dev, bool dma_enabled)
{
const struct crypto_cc23x0_config *cfg = dev->config;

dma_stop(cfg->dma_dev, cfg->dma_channel_b);
dma_stop(cfg->dma_dev, cfg->dma_channel_a);

AESDisableDMA();
#else
ARG_UNUSED(dev);
#endif

if (dma_enabled) {
pm_device_runtime_put(cfg->dma_dev);
}
}

#endif /* CONFIG_CRYPTO_CC23X0_DMA */

static void crypto_cc23x0_aes_cleanup(void)
{
AESClearAUTOCFGTrigger();
AESClearAUTOCFGBusHalt();
AESClearTXTAndBUF();
Expand All @@ -127,6 +171,7 @@ static int crypto_cc23x0_ecb_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *
#ifdef CONFIG_CRYPTO_CC23X0_DMA
uint32_t int_flags = AES_IMASK_CHBDONE;
const struct crypto_cc23x0_config *cfg = dev->config;
bool dma_enabled = false;

struct dma_block_config block_cfg_cha = {
.source_address = (uint32_t)(pkt->in_buf),
Expand Down Expand Up @@ -186,6 +231,8 @@ static int crypto_cc23x0_ecb_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *

k_mutex_lock(&data->device_mutex, K_FOREVER);

crypto_cc23x0_pm_policy_state_lock_get();

/* Enable interrupts */
AESSetIMASK(int_flags);

Expand All @@ -198,6 +245,11 @@ static int crypto_cc23x0_ecb_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *
AES_AUTOCFG_TRGAES_WRBUF3S);

#ifdef CONFIG_CRYPTO_CC23X0_DMA
ret = crypto_cc23x0_dma_enable(dev, &dma_enabled);
if (ret) {
goto cleanup;
}

/* Setup the DMA for the AES engine */
AESSetupDMA(AES_DMA_ADRCHA_BUF0 |
AES_DMA_TRGCHA_AESSTART |
Expand All @@ -209,11 +261,13 @@ static int crypto_cc23x0_ecb_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *

ret = dma_config(cfg->dma_dev, cfg->dma_channel_a, &dma_cfg_cha);
if (ret) {
LOG_ERR("Failed to configure DMA CHA");
goto cleanup;
}

ret = dma_config(cfg->dma_dev, cfg->dma_channel_b, &dma_cfg_chb);
if (ret) {
LOG_ERR("Failed to configure DMA CHB");
goto cleanup;
}

Expand Down Expand Up @@ -265,7 +319,11 @@ static int crypto_cc23x0_ecb_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *
#endif

cleanup:
crypto_cc23x0_cleanup(dev);
#ifdef CONFIG_CRYPTO_CC23X0_DMA
crypto_cc23x0_dma_cleanup(dev, dma_enabled);
#endif
crypto_cc23x0_aes_cleanup();
crypto_cc23x0_pm_policy_state_lock_put();
k_mutex_unlock(&data->device_mutex);
pkt->out_len = out_bytes_processed;

Expand All @@ -284,6 +342,7 @@ static int crypto_cc23x0_ctr(struct cipher_ctx *ctx, struct cipher_pkt *pkt, uin
#ifdef CONFIG_CRYPTO_CC23X0_DMA
uint32_t int_flags = AES_IMASK_CHBDONE;
const struct crypto_cc23x0_config *cfg = dev->config;
bool dma_enabled = false;

struct dma_block_config block_cfg_cha = {
.source_address = (uint32_t)(pkt->in_buf),
Expand Down Expand Up @@ -345,6 +404,8 @@ static int crypto_cc23x0_ctr(struct cipher_ctx *ctx, struct cipher_pkt *pkt, uin

k_mutex_lock(&data->device_mutex, K_FOREVER);

crypto_cc23x0_pm_policy_state_lock_get();

/* Enable interrupts */
AESSetIMASK(int_flags);

Expand All @@ -359,6 +420,11 @@ static int crypto_cc23x0_ctr(struct cipher_ctx *ctx, struct cipher_pkt *pkt, uin
AES_AUTOCFG_CTRSIZE_CTR128);

#ifdef CONFIG_CRYPTO_CC23X0_DMA
ret = crypto_cc23x0_dma_enable(dev, &dma_enabled);
if (ret) {
goto cleanup;
}

/* Setup the DMA for the AES engine */
AESSetupDMA(AES_DMA_ADRCHA_TXTX0 |
AES_DMA_TRGCHA_AESDONE |
Expand All @@ -367,11 +433,13 @@ static int crypto_cc23x0_ctr(struct cipher_ctx *ctx, struct cipher_pkt *pkt, uin

ret = dma_config(cfg->dma_dev, cfg->dma_channel_a, &dma_cfg_cha);
if (ret) {
LOG_ERR("Failed to configure DMA CHA");
goto cleanup;
}

ret = dma_config(cfg->dma_dev, cfg->dma_channel_b, &dma_cfg_chb);
if (ret) {
LOG_ERR("Failed to configure DMA CHB");
goto cleanup;
}

Expand Down Expand Up @@ -433,7 +501,11 @@ static int crypto_cc23x0_ctr(struct cipher_ctx *ctx, struct cipher_pkt *pkt, uin
#endif

cleanup:
crypto_cc23x0_cleanup(dev);
#ifdef CONFIG_CRYPTO_CC23X0_DMA
crypto_cc23x0_dma_cleanup(dev, dma_enabled);
#endif
crypto_cc23x0_aes_cleanup();
crypto_cc23x0_pm_policy_state_lock_put();
k_mutex_unlock(&data->device_mutex);
pkt->out_len = bytes_processed;

Expand All @@ -451,6 +523,7 @@ static int crypto_cc23x0_cmac(struct cipher_ctx *ctx, struct cipher_pkt *pkt,
#ifdef CONFIG_CRYPTO_CC23X0_DMA
uint32_t int_flags = AES_IMASK_CHADONE;
const struct crypto_cc23x0_config *cfg = dev->config;
bool dma_enabled = false;

struct dma_block_config block_cfg_cha = {
.source_address = (uint32_t)b0,
Expand Down Expand Up @@ -492,6 +565,8 @@ static int crypto_cc23x0_cmac(struct cipher_ctx *ctx, struct cipher_pkt *pkt,

k_mutex_lock(&data->device_mutex, K_FOREVER);

crypto_cc23x0_pm_policy_state_lock_get();

/* Enable interrupts */
AESSetIMASK(int_flags);

Expand All @@ -506,6 +581,13 @@ static int crypto_cc23x0_cmac(struct cipher_ctx *ctx, struct cipher_pkt *pkt,
/* Write zero'd IV */
AESWriteIV32(iv);

#ifdef CONFIG_CRYPTO_CC23X0_DMA
ret = crypto_cc23x0_dma_enable(dev, &dma_enabled);
if (ret) {
goto out;
}
#endif

if (b0) {
#ifdef CONFIG_CRYPTO_CC23X0_DMA
/* Setup the DMA for the AES engine */
Expand All @@ -514,6 +596,7 @@ static int crypto_cc23x0_cmac(struct cipher_ctx *ctx, struct cipher_pkt *pkt,

ret = dma_config(cfg->dma_dev, cfg->dma_channel_a, &dma_cfg_cha);
if (ret) {
LOG_ERR("Failed to configure DMA CHA");
goto out;
}

Expand Down Expand Up @@ -546,6 +629,7 @@ static int crypto_cc23x0_cmac(struct cipher_ctx *ctx, struct cipher_pkt *pkt,

ret = dma_config(cfg->dma_dev, cfg->dma_channel_a, &dma_cfg_cha);
if (ret) {
LOG_ERR("Failed to configure DMA CHA");
goto out;
}

Expand Down Expand Up @@ -578,6 +662,7 @@ static int crypto_cc23x0_cmac(struct cipher_ctx *ctx, struct cipher_pkt *pkt,

ret = dma_config(cfg->dma_dev, cfg->dma_channel_a, &dma_cfg_cha);
if (ret) {
LOG_ERR("Failed to configure DMA CHA");
goto out;
}

Expand Down Expand Up @@ -624,7 +709,11 @@ static int crypto_cc23x0_cmac(struct cipher_ctx *ctx, struct cipher_pkt *pkt,
AESReadTag(pkt->out_buf);

out:
crypto_cc23x0_cleanup(dev);
#ifdef CONFIG_CRYPTO_CC23X0_DMA
crypto_cc23x0_dma_cleanup(dev, dma_enabled);
#endif
crypto_cc23x0_aes_cleanup();
crypto_cc23x0_pm_policy_state_lock_put();
k_mutex_unlock(&data->device_mutex);
pkt->out_len = bytes_processed;

Expand Down Expand Up @@ -979,6 +1068,7 @@ static int crypto_cc23x0_init(const struct device *dev)
{
#ifdef CONFIG_CRYPTO_CC23X0_DMA
const struct crypto_cc23x0_config *cfg = dev->config;
int ret;
#endif
struct crypto_cc23x0_data *data = dev->data;

Expand All @@ -1000,6 +1090,12 @@ static int crypto_cc23x0_init(const struct device *dev)
if (!device_is_ready(cfg->dma_dev)) {
return -ENODEV;
}

ret = pm_device_runtime_enable(cfg->dma_dev);
if (ret) {
LOG_ERR("Failed to enable DMA runtime PM");
return ret;
}
#else
k_sem_init(&data->aes_done, 0, 1);
#endif
Expand All @@ -1015,6 +1111,33 @@ static DEVICE_API(crypto, crypto_enc_funcs) = {

static struct crypto_cc23x0_data crypto_cc23x0_dev_data;

#ifdef CONFIG_PM_DEVICE

static int crypto_cc23x0_pm_action(const struct device *dev, enum pm_device_action action)
{
int ret = 0;

switch (action) {
case PM_DEVICE_ACTION_SUSPEND:
CLKCTLDisable(CLKCTL_BASE, CLKCTL_LAES);
break;
case PM_DEVICE_ACTION_RESUME:
CLKCTLEnable(CLKCTL_BASE, CLKCTL_LAES);
break;
case PM_DEVICE_ACTION_TURN_ON:
case PM_DEVICE_ACTION_TURN_OFF:
break;
default:
ret = -ENOTSUP;
}

return ret;
}

#endif /* CONFIG_PM_DEVICE */

PM_DEVICE_DT_INST_DEFINE(0, crypto_cc23x0_pm_action);

#ifdef CONFIG_CRYPTO_CC23X0_DMA
static const struct crypto_cc23x0_config crypto_cc23x0_dev_config = {
.dma_dev = DEVICE_DT_GET(TI_CC23X0_DT_INST_DMA_CTLR(0, cha)),
Expand All @@ -1026,7 +1149,7 @@ static const struct crypto_cc23x0_config crypto_cc23x0_dev_config = {

DEVICE_DT_INST_DEFINE(0,
crypto_cc23x0_init,
NULL,
PM_DEVICE_DT_INST_GET(0),
&crypto_cc23x0_dev_data,
&crypto_cc23x0_dev_config,
POST_KERNEL,
Expand All @@ -1035,7 +1158,7 @@ DEVICE_DT_INST_DEFINE(0,
#else
DEVICE_DT_INST_DEFINE(0,
crypto_cc23x0_init,
NULL,
PM_DEVICE_DT_INST_GET(0),
&crypto_cc23x0_dev_data,
NULL,
POST_KERNEL,
Expand Down