Skip to content

Commit 34d888c

Browse files
LaurentiuM1234kartben
authored andcommitted
drivers: dai: esai: add support for runtime PM
Add support for runtime PM. Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
1 parent e11ca43 commit 34d888c

File tree

2 files changed

+103
-8
lines changed

2 files changed

+103
-8
lines changed

drivers/dai/nxp/esai/esai.c

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
/*
2-
* Copyright 2024 NXP
2+
* Copyright 2024-2025 NXP
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
#include <zephyr/pm/device_runtime.h>
8+
#include <zephyr/pm/device.h>
9+
710
#include "esai.h"
811

912
/* TODO:
@@ -654,14 +657,12 @@ static const struct dai_properties
654657

655658
static int esai_probe(const struct device *dev)
656659
{
657-
/* nothing to be done here but mandatory to implement */
658-
return 0;
660+
return pm_device_runtime_get(dev);
659661
}
660662

661663
static int esai_remove(const struct device *dev)
662664
{
663-
/* nothing to be done here but mandatory to implement */
664-
return 0;
665+
return pm_device_runtime_put(dev);
665666
}
666667

667668
static DEVICE_API(dai, esai_api) = {
@@ -673,6 +674,54 @@ static DEVICE_API(dai, esai_api) = {
673674
.remove = esai_remove,
674675
};
675676

677+
static int esai_clks_enable_disable(const struct device *dev, bool enable)
678+
{
679+
const struct esai_config *cfg;
680+
void *clk_id;
681+
int i, ret;
682+
683+
cfg = dev->config;
684+
685+
for (i = 0; i < cfg->clk_data.clock_num; i++) {
686+
clk_id = UINT_TO_POINTER(cfg->clk_data.clocks[i]);
687+
688+
if (enable) {
689+
ret = clock_control_on(cfg->clk_data.dev, clk_id);
690+
} else {
691+
ret = clock_control_off(cfg->clk_data.dev, clk_id);
692+
}
693+
694+
if (ret < 0) {
695+
LOG_ERR("failed to gate/ungate clock %u: %d",
696+
cfg->clk_data.clocks[i], ret);
697+
return ret;
698+
}
699+
}
700+
701+
return 0;
702+
}
703+
704+
__maybe_unused static int esai_pm_action(const struct device *dev,
705+
enum pm_device_action action)
706+
{
707+
bool enable = true;
708+
709+
switch (action) {
710+
case PM_DEVICE_ACTION_RESUME:
711+
break;
712+
case PM_DEVICE_ACTION_SUSPEND:
713+
enable = false;
714+
break;
715+
case PM_DEVICE_ACTION_TURN_ON:
716+
case PM_DEVICE_ACTION_TURN_OFF:
717+
return 0;
718+
default:
719+
return -ENOTSUP;
720+
}
721+
722+
return esai_clks_enable_disable(dev, enable);
723+
}
724+
676725
static int esai_init(const struct device *dev)
677726
{
678727
const struct esai_config *cfg;
@@ -684,12 +733,19 @@ static int esai_init(const struct device *dev)
684733

685734
device_map(&data->regmap, cfg->regmap_phys, cfg->regmap_size, K_MEM_CACHE_NONE);
686735

736+
#ifndef CONFIG_PM_DEVICE_RUNTIME
737+
ret = esai_clks_enable_disable(dev, true);
738+
if (ret < 0) {
739+
return ret;
740+
}
741+
#endif /* CONFIG_PM_DEVICE_RUNTIME */
742+
687743
ret = esai_parse_pinmodes(cfg, data);
688744
if (ret < 0) {
689745
return ret;
690746
}
691747

692-
return 0;
748+
return pm_device_runtime_enable(dev);
693749
}
694750

695751
#define ESAI_INIT(inst) \
@@ -749,14 +805,17 @@ static struct esai_config esai_config_##inst = { \
749805
.pinmodes_size = ARRAY_SIZE(pinmodes_##inst), \
750806
.clock_cfg = clock_cfg_##inst, \
751807
.clock_cfg_size = ARRAY_SIZE(clock_cfg_##inst), \
808+
.clk_data = ESAI_CLOCK_DATA_DECLARE(inst), \
752809
}; \
753810
\
754811
static struct esai_data esai_data_##inst = { \
755812
.cfg.type = DAI_IMX_ESAI, \
756813
.cfg.dai_index = DT_INST_PROP_OR(inst, dai_index, 0), \
757814
}; \
758815
\
759-
DEVICE_DT_INST_DEFINE(inst, &esai_init, NULL, \
816+
PM_DEVICE_DT_INST_DEFINE(inst, esai_pm_action); \
817+
\
818+
DEVICE_DT_INST_DEFINE(inst, &esai_init, PM_DEVICE_DT_INST_GET(inst), \
760819
&esai_data_##inst, &esai_config_##inst, \
761820
POST_KERNEL, CONFIG_DAI_INIT_PRIORITY, \
762821
&esai_api); \

drivers/dai/nxp/esai/esai.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 NXP
2+
* Copyright 2024-2025 NXP
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -11,6 +11,7 @@
1111
#include <zephyr/drivers/dai.h>
1212
#include <zephyr/device.h>
1313
#include <zephyr/dt-bindings/dai/esai.h>
14+
#include <zephyr/drivers/clock_control.h>
1415

1516
#include <fsl_esai.h>
1617

@@ -152,6 +153,34 @@ LOG_MODULE_REGISTER(nxp_dai_esai);
152153
#define ESAI_PIN_IS_USED(data, which)\
153154
(((data)->pcrc & BIT(which)) && ((data->prrc) & BIT(which)))
154155

156+
#define IDENTITY_VARGS(V, ...) IDENTITY(V)
157+
158+
#define _ESAI_CLOCK_INDEX_ARRAY(inst)\
159+
LISTIFY(DT_INST_PROP_LEN_OR(inst, clocks, 0), IDENTITY_VARGS, (,))
160+
161+
#define _ESAI_GET_CLOCK_ID(clock_idx, inst)\
162+
DT_INST_PHA_BY_IDX_OR(inst, clocks, clock_idx, name, 0x0)
163+
164+
#define _ESAI_CLOCK_ID_ARRAY(inst)\
165+
FOR_EACH_FIXED_ARG(_ESAI_GET_CLOCK_ID, (,), inst, _ESAI_CLOCK_INDEX_ARRAY(inst))
166+
167+
#define _ESAI_GET_CLOCK_ARRAY(inst) \
168+
COND_CODE_1(DT_NODE_HAS_PROP(DT_INST(inst, nxp_dai_esai), clocks), \
169+
({ _ESAI_CLOCK_ID_ARRAY(inst) }), \
170+
({ }))
171+
172+
#define _ESAI_GET_CLOCK_CONTROLLER(inst) \
173+
COND_CODE_1(DT_NODE_HAS_PROP(DT_INST(inst, nxp_dai_esai), clocks), \
174+
(DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst))), \
175+
(NULL))
176+
177+
#define ESAI_CLOCK_DATA_DECLARE(inst) \
178+
{ \
179+
.clocks = (uint32_t [])_ESAI_GET_CLOCK_ARRAY(inst), \
180+
.clock_num = DT_INST_PROP_LEN_OR(inst, clocks, 0), \
181+
.dev = _ESAI_GET_CLOCK_CONTROLLER(inst), \
182+
}
183+
155184
struct esai_data {
156185
mm_reg_t regmap;
157186
struct dai_config cfg;
@@ -170,6 +199,12 @@ struct esai_data {
170199
uint32_t pcrc;
171200
};
172201

202+
struct esai_clock_data {
203+
uint32_t clock_num;
204+
uint32_t *clocks;
205+
const struct device *dev;
206+
};
207+
173208
struct esai_config {
174209
uint32_t regmap_phys;
175210
uint32_t regmap_size;
@@ -182,6 +217,7 @@ struct esai_config {
182217
uint32_t pinmodes_size;
183218
uint32_t *clock_cfg;
184219
uint32_t clock_cfg_size;
220+
struct esai_clock_data clk_data;
185221
};
186222

187223
/* this needs to perfectly match SOF's struct sof_ipc_dai_esai_params */

0 commit comments

Comments
 (0)