Skip to content
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

nxp: imx8mp: support SDMA3 and SAI3 bus clock management #84972

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
46 changes: 46 additions & 0 deletions drivers/clock_control/clock_control_mcux_ccm.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ static const clock_ip_name_t sai_clocks[] = {
kCLOCK_AUDIO_Sai3,
dbaluta marked this conversation as resolved.
Show resolved Hide resolved
};
#endif

#if defined(CONFIG_SOC_MIMX8ML8_ADSP)
static const clock_ip_name_t sai_clocks[] = {
kCLOCK_Sai1,
kCLOCK_Sai2,
kCLOCK_Sai3,
};
#endif /* CONFIG_SOC_MIMX8ML8_ADSP */
#endif /* CONFIG_DAI_NXP_SAI */
dbaluta marked this conversation as resolved.
Show resolved Hide resolved

#if defined(CONFIG_I2C_NXP_II2C)
Expand All @@ -94,6 +102,14 @@ static const clock_ip_name_t i2c_clk_root[] = {
};
#endif

#if defined(CONFIG_DMA_NXP_SDMA)
static const clock_ip_name_t sdma_clocks[] = {
kCLOCK_Sdma1,
kCLOCK_Sdma2,
kCLOCK_Sdma3,
};
#endif /* CONFIG_DMA_NXP_SDMA */
dbaluta marked this conversation as resolved.
Show resolved Hide resolved

static int mcux_ccm_on(const struct device *dev,
clock_control_subsys_t sub_system)
{
Expand All @@ -110,6 +126,14 @@ static int mcux_ccm_on(const struct device *dev,
return 0;
#endif

#ifdef CONFIG_DMA_NXP_SDMA
case IMX_CCM_SDMA1_CLK:
case IMX_CCM_SDMA2_CLK:
case IMX_CCM_SDMA3_CLK:
CLOCK_EnableClock(sdma_clocks[instance]);
return 0;
#endif /* CONFIG_DMA_NXP_SDMA */

#if defined(CONFIG_UART_MCUX_LPUART) && defined(CONFIG_SOC_MIMX8QM6_ADSP)
case IMX_CCM_LPUART1_CLK:
case IMX_CCM_LPUART2_CLK:
Expand Down Expand Up @@ -137,6 +161,13 @@ static int mcux_ccm_on(const struct device *dev,
CLOCK_EnableClock(sai_clocks[instance]);
return 0;
#endif
#if defined(CONFIG_SOC_MIMX8ML8_ADSP)
case IMX_CCM_SAI1_CLK:
dbaluta marked this conversation as resolved.
Show resolved Hide resolved
case IMX_CCM_SAI2_CLK:
case IMX_CCM_SAI3_CLK:
CLOCK_EnableClock(sai_clocks[instance]);
return 0;
#endif /* CONFIG_SOC_MIMX8ML8_ADSP */
#endif /* CONFIG_DAI_NXP_SAI */

#if defined(CONFIG_ETH_NXP_ENET)
Expand Down Expand Up @@ -171,6 +202,14 @@ static int mcux_ccm_off(const struct device *dev,
return 0;
#endif

#ifdef CONFIG_DMA_NXP_SDMA
case IMX_CCM_SDMA1_CLK:
case IMX_CCM_SDMA2_CLK:
case IMX_CCM_SDMA3_CLK:
CLOCK_DisableClock(sdma_clocks[instance]);
return 0;
#endif /* CONFIG_DMA_NXP_SDMA */

#ifdef CONFIG_DAI_NXP_SAI
#if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP)
case IMX_CCM_SAI1_CLK:
Expand All @@ -179,6 +218,13 @@ static int mcux_ccm_off(const struct device *dev,
CLOCK_DisableClock(sai_clocks[instance]);
return 0;
#endif
#if defined(CONFIG_SOC_MIMX8ML8_ADSP)
case IMX_CCM_SAI1_CLK:
dbaluta marked this conversation as resolved.
Show resolved Hide resolved
case IMX_CCM_SAI2_CLK:
case IMX_CCM_SAI3_CLK:
CLOCK_DisableClock(sai_clocks[instance]);
return 0;
#endif /* CONFIG_SOC_MIMX8ML8_ADSP */
#endif /* CONFIG_DAI_NXP_SAI */
default:
(void)instance;
Expand Down
4 changes: 2 additions & 2 deletions drivers/dai/nxp/sai/sai.c
Original file line number Diff line number Diff line change
Expand Up @@ -839,9 +839,9 @@ static int sai_clks_enable_disable(const struct device *dev, bool enable)
clk_id = UINT_TO_POINTER(cfg->clk_data.clocks[i]);

if (enable) {
ret = clock_control_on(cfg->clk_data.dev, clk_id);
ret = clock_control_on(cfg->clk_data.devs[i], clk_id);
} else {
ret = clock_control_off(cfg->clk_data.dev, clk_id);
ret = clock_control_off(cfg->clk_data.devs[i], clk_id);
}

if (ret < 0) {
Expand Down
31 changes: 18 additions & 13 deletions drivers/dai/nxp/sai/sai.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ LOG_MODULE_REGISTER(nxp_dai_sai);
#define _SAI_GET_CLOCK_NAME(clock_idx, inst)\
DT_INST_PROP_BY_IDX(inst, clock_names, clock_idx)

#define _SAI_GET_CLOCK_CTLR_DEV(clock_idx, inst)\
DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_IDX(inst, clock_idx))

/* used to convert the clocks property into an array of clock IDs */
#define _SAI_CLOCK_ID_ARRAY(inst)\
FOR_EACH_FIXED_ARG(_SAI_GET_CLOCK_ID, (,), inst, _SAI_CLOCK_INDEX_ARRAY(inst))
Expand All @@ -52,6 +55,9 @@ LOG_MODULE_REGISTER(nxp_dai_sai);
#define _SAI_CLOCK_NAME_ARRAY(inst)\
FOR_EACH_FIXED_ARG(_SAI_GET_CLOCK_NAME, (,), inst, _SAI_CLOCK_INDEX_ARRAY(inst))

#define _SAI_CLOCK_CTRL_ARRAY(inst)\
FOR_EACH_FIXED_ARG(_SAI_GET_CLOCK_CTLR_DEV, (,), inst, _SAI_CLOCK_INDEX_ARRAY(inst))

/* used to convert a clocks property into an array of clock IDs. If the property
* is not specified then this macro will return {}.
*/
Expand All @@ -64,10 +70,10 @@ LOG_MODULE_REGISTER(nxp_dai_sai);
* It is assumed that all SAI clocks come from a single clock provider.
* This macro returns a NULL if the clocks property doesn't exist.
*/
#define _SAI_GET_CLOCK_CONTROLLER(inst)\
COND_CODE_1(DT_NODE_HAS_PROP(DT_INST(inst, nxp_dai_sai), clocks),\
(DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst))),\
(NULL))
#define _SAI_GET_CLOCK_CONTROLLERS(inst) \
COND_CODE_1(DT_NODE_HAS_PROP(DT_INST(inst, nxp_dai_sai), clocks), \
({ _SAI_CLOCK_CTRL_ARRAY(inst) }), \
({ }))

/* used to convert a clock-names property into an array of clock names. If the
* property is not specified then this macro will return {}.
Expand All @@ -78,12 +84,12 @@ LOG_MODULE_REGISTER(nxp_dai_sai);
({ }))

/* used to declare a struct clock_data */
#define SAI_CLOCK_DATA_DECLARE(inst) \
{ \
.clocks = (uint32_t [])_SAI_GET_CLOCK_ARRAY(inst), \
.clock_num = DT_INST_PROP_LEN_OR(inst, clocks, 0), \
.dev = _SAI_GET_CLOCK_CONTROLLER(inst), \
.clock_names = (const char *[])_SAI_GET_CLOCK_NAMES(inst), \
#define SAI_CLOCK_DATA_DECLARE(inst) \
{ \
.clocks = (uint32_t [])_SAI_GET_CLOCK_ARRAY(inst), \
.clock_num = DT_INST_PROP_LEN_OR(inst, clocks, 0), \
.devs = (const struct device *[])_SAI_GET_CLOCK_CONTROLLERS(inst), \
.clock_names = (const char *[])_SAI_GET_CLOCK_NAMES(inst), \
}

/* used to parse the tx-fifo-watermark property. If said property is not
Expand Down Expand Up @@ -240,8 +246,7 @@ LOG_MODULE_REGISTER(nxp_dai_sai);
struct sai_clock_data {
uint32_t *clocks;
uint32_t clock_num;
/* assumption: all clocks belong to the same producer */
const struct device *dev;
const struct device **devs;
const char **clock_names;
};

Expand Down Expand Up @@ -369,7 +374,7 @@ static int get_mclk_rate(const struct sai_clock_data *clk_data,
return clk_idx;
}

return clock_control_get_rate(clk_data->dev,
return clock_control_get_rate(clk_data->devs[clk_idx],
UINT_TO_POINTER(clk_data->clocks[clk_idx]),
rate);
}
Expand Down
74 changes: 72 additions & 2 deletions drivers/dma/dma_nxp_sdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include <zephyr/irq.h>
#include <zephyr/cache.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device_runtime.h>
#include <zephyr/pm/device.h>
#include <zephyr/drivers/clock_control.h>
#include "fsl_sdma.h"

LOG_MODULE_REGISTER(nxp_sdma);
Expand All @@ -23,6 +26,8 @@ AT_NONCACHEABLE_SECTION_ALIGN(static sdma_context_data_t
struct sdma_dev_cfg {
SDMAARM_Type *base;
void (*irq_config)(void);
const struct device *clk_dev;
uint32_t bus_clk_id;
};

struct sdma_channel_data {
Expand Down Expand Up @@ -422,9 +427,66 @@ static bool sdma_channel_filter(const struct device *dev, int chan_id, void *par
dev_data->chan[chan_id].event_source = *((int *)param);
dev_data->chan[chan_id].index = chan_id;

if (pm_device_runtime_get(dev) < 0) {
LOG_ERR("failed to runtime get");
return false;
}

return true;
}

static void sdma_channel_release(const struct device *dev, uint32_t chan_id)
{
if (chan_id == 0) {
return;
}

if (chan_id >= FSL_FEATURE_SDMA_MODULE_CHANNEL) {
return;
}

if (pm_device_runtime_put(dev) < 0) {
LOG_ERR("failed to runtime put");
return;
}
}

static int sdma_bus_clk_enable_disable(const struct device *dev, bool enable)
{
const struct sdma_dev_cfg *cfg = dev->config;

if (!cfg->clk_dev) {
return -ENODEV;
}

if (enable) {
return clock_control_on(cfg->clk_dev,
UINT_TO_POINTER(cfg->bus_clk_id));
} else {
return clock_control_off(cfg->clk_dev,
UINT_TO_POINTER(cfg->bus_clk_id));
}
}

__maybe_unused static int sdma_pm_action(const struct device *dev,
enum pm_device_action action)
{
bool enable = true;

switch (action) {
case PM_DEVICE_ACTION_RESUME:
break;
case PM_DEVICE_ACTION_SUSPEND:
enable = false;
break;
case PM_DEVICE_ACTION_TURN_ON:
case PM_DEVICE_ACTION_TURN_OFF:
return 0;
}

return sdma_bus_clk_enable_disable(dev, enable);
}

static DEVICE_API(dma, sdma_api) = {
.reload = dma_nxp_sdma_reload,
.config = dma_nxp_sdma_config,
Expand All @@ -435,6 +497,7 @@ static DEVICE_API(dma, sdma_api) = {
.get_status = dma_nxp_sdma_get_status,
.get_attribute = dma_nxp_sdma_get_attribute,
.chan_filter = sdma_channel_filter,
.chan_release = sdma_channel_release,
};

static int dma_nxp_sdma_init(const struct device *dev)
Expand All @@ -450,12 +513,13 @@ static int dma_nxp_sdma_init(const struct device *dev)
SDMA_GetDefaultConfig(&defconfig);
defconfig.ratio = kSDMA_ARMClockFreq;

/* this also ungates the bus clock */
SDMA_Init(cfg->base, &defconfig);

/* configure interrupts */
cfg->irq_config();

return 0;
return pm_device_runtime_enable(dev);
}

#define DMA_NXP_SDMA_INIT(inst) \
Expand All @@ -468,6 +532,8 @@ static int dma_nxp_sdma_init(const struct device *dev)
static const struct sdma_dev_cfg sdma_cfg_##inst = { \
.base = (SDMAARM_Type *)DT_INST_REG_ADDR(inst), \
.irq_config = dma_nxp_sdma_##inst_irq_config, \
.clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \
.bus_clk_id = DT_INST_CLOCKS_CELL(inst, name), \
}; \
static void dma_nxp_sdma_##inst_irq_config(void) \
{ \
Expand All @@ -476,7 +542,11 @@ static int dma_nxp_sdma_init(const struct device *dev)
dma_nxp_sdma_isr, DEVICE_DT_INST_GET(inst), 0); \
irq_enable(DT_INST_IRQN(inst)); \
} \
DEVICE_DT_INST_DEFINE(inst, &dma_nxp_sdma_init, NULL, \
\
PM_DEVICE_DT_INST_DEFINE(inst, sdma_pm_action); \
\
DEVICE_DT_INST_DEFINE(inst, &dma_nxp_sdma_init, \
PM_DEVICE_DT_INST_GET(inst), \
&sdma_data_##inst, &sdma_cfg_##inst, \
PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, \
&sdma_api); \
Expand Down
5 changes: 3 additions & 2 deletions dts/xtensa/nxp/nxp_imx8m.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
sdma3: dma@30e00000 {
compatible = "nxp,sdma";
reg = <0x30e00000 DT_SIZE_K(64)>;
clocks = <&ccm IMX_CCM_SDMA3_CLK 0x0 0x0>;
interrupt-parent = <&master1>;
interrupts = <2 0 0>;
#dma-cells = <2>;
Expand All @@ -101,8 +102,8 @@
reg = <0x30c30000 DT_SIZE_K(64)>;

mclk-is-output;
clocks = <&mclk1>;
clock-names = "mclk1";
clocks = <&ccm IMX_CCM_SAI3_CLK 0x0 0x0>, <&mclk1>;
clock-names = "bus", "mclk1";

interrupt-parent = <&master1>;
interrupts = <18>;
Expand Down
4 changes: 4 additions & 0 deletions include/zephyr/dt-bindings/clock/imx_ccm.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,8 @@
#define IMX_CCM_I2C5_CLK 0x1404UL
#define IMX_CCM_I2C6_CLK 0x1405UL

#define IMX_CCM_SDMA1_CLK 0x1500UL
#define IMX_CCM_SDMA2_CLK 0x1501UL
#define IMX_CCM_SDMA3_CLK 0x1502UL

#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_IMX_CCM_H_ */
2 changes: 1 addition & 1 deletion west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ manifest:
groups:
- hal
- name: hal_nxp
revision: 49ff7e33f848e4b59da59369a77da63e346fb1a3
revision: pull/503/head
path: modules/hal/nxp
groups:
- hal
Expand Down
Loading