From 58e74d8ffeba6fecef2178c13e3be61b97ee7edb Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 31 Jan 2025 13:44:19 +0200 Subject: [PATCH 1/5] manifest: update hal_nxp Pull in the following patches: devices: MIMX8ML8: fsl_clock: fix root clock gating/ungating devices: MIMX8ML8: fsl_clock: change root clock ID for SAI3 Signed-off-by: Laurentiu Mihalcea --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index c005d3f727e8..2fd2deb517b8 100644 --- a/west.yml +++ b/west.yml @@ -203,7 +203,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 49ff7e33f848e4b59da59369a77da63e346fb1a3 + revision: pull/503/head path: modules/hal/nxp groups: - hal From f8af332ce68254f2fa119bb3b44525fe0a01b336 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Wed, 29 Jan 2025 15:12:52 +0200 Subject: [PATCH 2/5] drivers: dai: sai: support clocks from multiple providers Current SAI code only supports clocks from a single provider. As such, add support for having clocks from multiple, different providers. Signed-off-by: Laurentiu Mihalcea --- drivers/dai/nxp/sai/sai.c | 4 ++-- drivers/dai/nxp/sai/sai.h | 31 ++++++++++++++++++------------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/dai/nxp/sai/sai.c b/drivers/dai/nxp/sai/sai.c index c99eecd856f2..0d2223f1dd22 100644 --- a/drivers/dai/nxp/sai/sai.c +++ b/drivers/dai/nxp/sai/sai.c @@ -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) { diff --git a/drivers/dai/nxp/sai/sai.h b/drivers/dai/nxp/sai/sai.h index 070427443346..7b22da10f594 100644 --- a/drivers/dai/nxp/sai/sai.h +++ b/drivers/dai/nxp/sai/sai.h @@ -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)) @@ -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 {}. */ @@ -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 {}. @@ -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 @@ -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; }; @@ -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); } From e69a7d4e484cd4dbcbd4a7c0e1acc90f6799781b Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Wed, 29 Jan 2025 15:15:15 +0200 Subject: [PATCH 3/5] clock_control: mcux_ccm: add SAI and SDMA clocks Add SAI1-3 and SDMA1-3 bus clocks for imx8mp. Signed-off-by: Laurentiu Mihalcea --- .../clock_control/clock_control_mcux_ccm.c | 46 +++++++++++++++++++ include/zephyr/dt-bindings/clock/imx_ccm.h | 4 ++ 2 files changed, 50 insertions(+) diff --git a/drivers/clock_control/clock_control_mcux_ccm.c b/drivers/clock_control/clock_control_mcux_ccm.c index 5ae8d71d979d..e523f56b317b 100644 --- a/drivers/clock_control/clock_control_mcux_ccm.c +++ b/drivers/clock_control/clock_control_mcux_ccm.c @@ -79,6 +79,14 @@ static const clock_ip_name_t sai_clocks[] = { kCLOCK_AUDIO_Sai3, }; #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 */ #if defined(CONFIG_I2C_NXP_II2C) @@ -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 */ + static int mcux_ccm_on(const struct device *dev, clock_control_subsys_t sub_system) { @@ -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: @@ -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: + 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) @@ -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: @@ -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: + 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; diff --git a/include/zephyr/dt-bindings/clock/imx_ccm.h b/include/zephyr/dt-bindings/clock/imx_ccm.h index 4f2f1bb09525..116df719b90c 100644 --- a/include/zephyr/dt-bindings/clock/imx_ccm.h +++ b/include/zephyr/dt-bindings/clock/imx_ccm.h @@ -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_ */ From 598e81e988182243615e6f82c94410e1759b227d Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Wed, 29 Jan 2025 15:18:09 +0200 Subject: [PATCH 4/5] dts: xtensa: nxp_imx8m: add SAI3 and SDMA3 bus clocks Add SAI3 and SDMA3 bus clocks. Signed-off-by: Laurentiu Mihalcea --- dts/xtensa/nxp/nxp_imx8m.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dts/xtensa/nxp/nxp_imx8m.dtsi b/dts/xtensa/nxp/nxp_imx8m.dtsi index a18b63bf49e2..f5dc60abc13e 100644 --- a/dts/xtensa/nxp/nxp_imx8m.dtsi +++ b/dts/xtensa/nxp/nxp_imx8m.dtsi @@ -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>; @@ -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>; From 11a42578959f31349584196b37a79ef829458fe0 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Wed, 29 Jan 2025 16:48:39 +0200 Subject: [PATCH 5/5] dma: dma_nxp_sdma: support pm runtime operations Add support for PM runtime operations. Signed-off-by: Laurentiu Mihalcea --- drivers/dma/dma_nxp_sdma.c | 74 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/dma/dma_nxp_sdma.c b/drivers/dma/dma_nxp_sdma.c index 380a9411c9e3..c359c0eeeca4 100644 --- a/drivers/dma/dma_nxp_sdma.c +++ b/drivers/dma/dma_nxp_sdma.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include "fsl_sdma.h" LOG_MODULE_REGISTER(nxp_sdma); @@ -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 { @@ -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, @@ -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) @@ -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) \ @@ -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) \ { \ @@ -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); \