#include <zephyr/init.h>
#include <fsl_clock.h>
#include <fsl_iomuxc.h>
/**
* @brief Early system hook to force MCLK generation for the SGTL5000 codec.
*
* The NXP SGTL5000 audio codec digital state machine is entirely clocked by the
* external MCLK line. It will stay in absolute hardware freeze and refuse to
* acknowledge any I2C control frames until a valid clock signal is present.
*
* This function bypasses the default dynamic clock gating of the Zephyr SAI driver,
* forcing the i.MX RT1024 to output a continuous clock stream prior to kernel
* device driver initialization loops.
*/
static int sgtl5000_force_mclk_init(void)
{
/* 1. Force the physical pinmux allocation for the SAI2 MCLK signal line */
/* Target Pin: GPIO_SD_B0_00 configured to Alternative Mode 3 (SAI2_MCLK) */
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B0_00_SAI2_MCLK, 0U);
/* 2. Configure electrical pads parameters for high-frequency clock transmission */
/* Settings: Speed=Medium, Drive Strength=R0/6, Slew Rate=Fast, Pull=Disabled */
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_00_SAI2_MCLK, 0x10B0U);
/* 3. Enable the main peripheral clock gate inside the i.MX RT Clock Controller */
CLOCK_EnableClock(kCLOCK_Sai2);
/* 4. Configure Root Clock Multiplexers and Divider Trees for SAI2 */
/* Select PLL4 (Audio PLL) as the clock source upstream root */
CLOCK_SetMux(kCLOCK_Sai2Mux, 0);
/* Set the pre-divider factor */
CLOCK_SetDiv(kCLOCK_Sai2PreDiv, 3);
/* Set the post-divider fraction to achieve exact ~12.288 MHz target */
CLOCK_SetDiv(kCLOCK_Sai2Div, 7);
/* 5. Force the internal SAI2 Master Control register to broadcast the clock line */
/* Set the Bit Clock Enable (BCE) bit to activate the generation engine */
SAI2->TCSR |= I2S_TCSR_BCE_MASK;
printk("SGTL5000 Driver Patch: Forced continuous MCLK line generation activated.\n");
return 0;
}
/*
* Register the function to run at the PRE_KERNEL_2 boot phase.
* Priority 50 ensures this executes before POST_KERNEL, which is when
* Zephyr processes the I2C bus device discovery array for audio codecs.
*/
SYS_INIT(sgtl5000_force_mclk_init, PRE_KERNEL_2, 50);