From 2995536f970f70547c877ab9c8e703541e2c8ae4 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 31 Jan 2025 13:23:50 +0200 Subject: [PATCH 1/2] devices: MIMX8ML8: fsl_clock: fix root clock gating/ungating The AUDIOMIX_TUPLE_ROOT() macro returns the ID of the root clock, while CCM_TUPLE_ROOT() returns the address of the register corresponding to the root clock. As such, the 'rootClk' variable can't be directly used with CCM_REG_CLR(), which expects the address of the CCM register for the root clock. Fix this by: 1) Introducing 2 new macros: CCM_TUPLE_ROOT_ID() and CCM_TUPLE_ROOT_ID(), which extract the ID of the root clock. This way, we can use the resulting ID in the same way for clocks managed by the AUDIOMIX block control and the CCM. 2) Translating the resulting root clock ID from step 1 to a CCM register. Signed-off-by: Laurentiu Mihalcea --- devices/MIMX8ML8/drivers/fsl_clock.c | 18 +++++++++++------- devices/MIMX8ML8/drivers/fsl_clock.h | 5 +++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/devices/MIMX8ML8/drivers/fsl_clock.c b/devices/MIMX8ML8/drivers/fsl_clock.c index 5ea20ec5e..8fde4bef0 100644 --- a/devices/MIMX8ML8/drivers/fsl_clock.c +++ b/devices/MIMX8ML8/drivers/fsl_clock.c @@ -920,25 +920,27 @@ void CLOCK_EnableClock(clock_ip_name_t ccmGate) { uint32_t clockType = CLOCK_GATE_TYPE(ccmGate); uint32_t ccgr = CCM_TUPLE_CCGR(ccmGate); - uint32_t rootClk = 0U; + uint32_t rootClk = 0U; + uint32_t rootClkId = 0U; if (CLOCK_GATE_IN_AUDIOMIX == clockType) { uint32_t offset = AUDIOMIX_TUPLE_OFFSET(ccmGate); uint32_t gate = AUDIOMIX_TUPLE_GATE(ccmGate); - rootClk = AUDIOMIX_TUPLE_ROOT(ccmGate); + rootClkId = AUDIOMIX_TUPLE_ROOT_ID(ccmGate); *(volatile uint32_t *)((uintptr_t)AUDIOMIX + offset) |= (uint32_t)1U << gate; } else { CCM_REG_SET(ccgr) = (uint32_t)kCLOCK_ClockNeededAll; - rootClk = CCM_TUPLE_ROOT(ccmGate); + rootClkId = CCM_TUPLE_ROOT_ID(ccmGate); } /* if root clock is 0xFFFFU, then skip enable root clock */ - if (rootClk != 0xFFFFU) + if (rootClkId != 0xFFFFU) { + rootClk = CCM_TUPLE_ROOT(rootClkId); CCM_REG_SET(rootClk) = CCM_TARGET_ROOT_SET_ENABLE_MASK; } } @@ -957,24 +959,26 @@ void CLOCK_DisableClock(clock_ip_name_t ccmGate) uint32_t ccgr = CCM_TUPLE_CCGR(ccmGate); uint32_t clockType = CLOCK_GATE_TYPE(ccmGate); uint32_t rootClk = 0U; + uint32_t rootClkId = 0U; if (CLOCK_GATE_IN_AUDIOMIX == clockType) { uint32_t offset = AUDIOMIX_TUPLE_OFFSET(ccmGate); uint32_t gate = AUDIOMIX_TUPLE_GATE(ccmGate); - rootClk = AUDIOMIX_TUPLE_ROOT(ccmGate); + rootClkId = AUDIOMIX_TUPLE_ROOT_ID(ccmGate); *(volatile uint32_t *)((uintptr_t)AUDIOMIX + offset) &= ~((uint32_t)1U << gate); } else { CCM_REG(ccgr) = (uint32_t)kCLOCK_ClockNotNeeded; - rootClk = CCM_TUPLE_ROOT(ccmGate); + rootClkId = CCM_TUPLE_ROOT(ccmGate); } /* if root clock is 0xFFFFU, then skip disable root clock */ - if (rootClk != 0xFFFFU) + if (rootClkId != 0xFFFFU) { + rootClk = CCM_TUPLE_ROOT(rootClkId); CCM_REG_CLR(rootClk) = CCM_TARGET_ROOT_CLR_ENABLE_MASK; } } diff --git a/devices/MIMX8ML8/drivers/fsl_clock.h b/devices/MIMX8ML8/drivers/fsl_clock.h index d70de7144..259f6bd9b 100644 --- a/devices/MIMX8ML8/drivers/fsl_clock.h +++ b/devices/MIMX8ML8/drivers/fsl_clock.h @@ -233,13 +233,14 @@ #define CLOCK_GATE_TYPE(tuple) ((uint32_t)(tuple) >> 28U) #define CCM_TUPLE(ccgr, root) ((((ccgr)&0xFFFFU) << 16U) | (root)) #define CCM_TUPLE_CCGR(tuple) ((uintptr_t)(&(CCM)->CCGR[(uint32_t)(tuple) >> 16U].CCGR)) -#define CCM_TUPLE_ROOT(tuple) ((uintptr_t)(&(CCM)->ROOT[(uint32_t)(tuple)&0xFFFFU].TARGET_ROOT)) +#define CCM_TUPLE_ROOT_ID(tuple) ((uint32_t)(tuple)&0xFFFFU) +#define CCM_TUPLE_ROOT(id) ((uintptr_t)(&(CCM)->ROOT[id].TARGET_ROOT)) /*!@brief audio mix CCGR */ #define AUDIOMIX_TUPLE(offset, gate, root) \ (((CLOCK_GATE_IN_AUDIOMIX) << 28U) | (((offset)&0xFU) << 24U) | (((gate)&0xFFU) << 16U) | ((root)&0xFFFFU)) #define AUDIOMIX_TUPLE_OFFSET(tuple) (((uint32_t)(tuple) >> 24U) & 0xFU) #define AUDIOMIX_TUPLE_GATE(tuple) (((uint32_t)(tuple) >> 16U) & 0xFFU) -#define AUDIOMIX_TUPLE_ROOT(tuple) ((uint32_t)(tuple)&0xFFFFU) +#define AUDIOMIX_TUPLE_ROOT_ID(tuple) ((uint32_t)(tuple)&0xFFFFU) /*! * @brief clock root source From 45d931b4acc6cf1624d347ab43aa5ec3a4663304 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 31 Jan 2025 13:25:28 +0200 Subject: [PATCH 2/2] devices: MIMX8ML8: fsl_clock: change root clock ID for SAI3 According to the TRM, the parent of the SAI3 bus clock is not SAI3_ROOT, but AUDIO_AHB_CLK_ROOT. As such, the currently used root parent ID (77) is wrong. Furthermore, CLOCK_EnableClock() and CLOCK_DisableClock() also attempt to ungate/gate the root parent of the AUDIOMIX clock. Since AUDIO_AHB_CLK_ROOT is the parent of multiple SAI bus clocks, allowing it to be gated during CLOCK_DisableClock() is not safe. As such, set the parent of SAI3 bus clock to 0xFFFF. This way, CLOCK_DisableClock() and CLOCK_EnableClock() will not attempt to gate/ungate it. This means that gating/ungating AUDIO_AHB_CLK_ROOT will have to be performed explicitly. Signed-off-by: Laurentiu Mihalcea --- devices/MIMX8ML8/drivers/fsl_clock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devices/MIMX8ML8/drivers/fsl_clock.h b/devices/MIMX8ML8/drivers/fsl_clock.h index 259f6bd9b..5743492c9 100644 --- a/devices/MIMX8ML8/drivers/fsl_clock.h +++ b/devices/MIMX8ML8/drivers/fsl_clock.h @@ -636,7 +636,7 @@ typedef enum _clock_ip_name kCLOCK_Sai3_Mclk3 = AUDIOMIX_TUPLE(0U, 11U, 0xFFFF), /*!< SAI3 MCLK3 clock gate */ kCLOCK_Sai3_Mclk2 = AUDIOMIX_TUPLE(0U, 10U, 0xFFFF), /*!< SAI3 MCLK2 clock gate */ kCLOCK_Sai3_Mclk1 = AUDIOMIX_TUPLE(0U, 9U, 0xFFFF), /*!< SAI3 MCLK1 clock gate */ - kCLOCK_Sai3 = AUDIOMIX_TUPLE(0U, 8U, 77U), /*!< SAI3 clock gate */ + kCLOCK_Sai3 = AUDIOMIX_TUPLE(0U, 8U, 0xFFFF), /*!< SAI3 clock gate */ kCLOCK_Sai2_Mclk3 = AUDIOMIX_TUPLE(0U, 7U, 0xFFFF), /*!< SAI2 MCLK3 clock gate */ kCLOCK_Sai2_Mclk2 = AUDIOMIX_TUPLE(0U, 6U, 0xFFFF), /*!< SAI2 MCLK2 clock gate */