Загрузка данных
#include <zephyr/init.h>
#include <zephyr/drivers/pinctrl.h>
#include <fsl_clock.h>
/* Helper macros to extract hardware configurations safely */
#define CODEC_SAI_NODE(inst) DT_PHANDLE(DT_DRV_INST(inst), bus_sai)
#define CODEC_SAI_BASE(inst) DT_REG_ADDR(CODEC_SAI_NODE(inst))
/**
* 1. Global Scope Pinctrl Definition.
* This macro automatically allocates individual pinctrl configuration data
* structures for EVERY active instance globally, resolving the visibility error.
*/
#define DEFINE_PINCTRL_FOR_INSTANCE(inst) PINCTRL_DT_DEV_CONFIG_DEFINE(DT_DRV_INST(inst));
DT_INST_FOREACH_STATUS_OKAY(DEFINE_PINCTRL_FOR_INSTANCE)
/**
* @brief Platform-agnostic helper to parse and apply the system clock tree configurations.
*/
static void sgtl5000_apply_clock_gate(uint32_t base_addr)
{
if (base_addr == DT_REG_ADDR(DT_NODELABEL(sai1))) {
CLOCK_EnableClock(kCLOCK_Sai1);
CLOCK_SetMux(kCLOCK_Sai1Mux, 0); /* Select PLL4 (Audio PLL) */
CLOCK_SetDiv(kCLOCK_Sai1PreDiv, 3);
CLOCK_SetDiv(kCLOCK_Sai1Div, 7);
} else if (base_addr == DT_REG_ADDR(DT_NODELABEL(sai2))) {
CLOCK_EnableClock(kCLOCK_Sai2);
CLOCK_SetMux(kCLOCK_Sai2Mux, 0); /* Select PLL4 (Audio PLL) */
CLOCK_SetDiv(kCLOCK_Sai2PreDiv, 3);
CLOCK_SetDiv(kCLOCK_Sai2Div, 7);
} else if (base_addr == DT_REG_ADDR(DT_NODELABEL(sai3))) {
CLOCK_EnableClock(kCLOCK_Sai3);
CLOCK_SetMux(kCLOCK_Sai3Mux, 0); /* Select PLL4 (Audio PLL) */
CLOCK_SetDiv(kCLOCK_Sai3PreDiv, 3);
CLOCK_SetDiv(kCLOCK_Sai3Div, 7);
}
}
/**
* 2. Execution block inside the multi-instance boot cycle framework.
*/
#define CONFIGURE_MCLK_FOR_INSTANCE(inst) \
do { \
/* Get the globally defined pinctrl structure configuration reference */ \
const struct pinctrl_dev_config *pcfg = \
PINCTRL_DT_DEV_CONFIG_GET(DT_DRV_INST(inst)); \
\
/* Safely apply hardware pin multiplexing configuration states */ \
int p_ret = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); \
if (p_ret < 0) { \
printk("SGTL5000 Early Pinmux Error: Pinctrl state failed for inst %d\n", \
inst); \
} \
\
/* Turn on clock configuration trees based on target SAI base address */ \
uint32_t base_addr = CODEC_SAI_BASE(inst); \
sgtl5000_apply_clock_gate(base_addr); \
\
/* Force un-gate continuous bit clock transmission stream */ \
((I2S_Type *)base_addr)->TCSR |= I2S_TCSR_BCE_MASK; \
\
printk("SGTL5000 Patch: Successfully un-gated MCLK on instance %d (SAI: 0x%08X)\n",\
inst, base_addr); \
} while (0);
static int sgtl5000_global_force_mclk_init(void)
{
/* Run the dynamic initialization sequence loops for all compiled node targets */
DT_INST_FOREACH_STATUS_OKAY(CONFIGURE_MCLK_FOR_INSTANCE)
return 0;
}
/* Run at PRE_KERNEL_2 phase to unlock I2C engines before standard post-kernel driver discovery */
SYS_INIT(sgtl5000_global_force_mclk_init, PRE_KERNEL_2, 50);