Загрузка данных
#include <zephyr/init.h>
#include <zephyr/drivers/pinctrl.h>
#include <fsl_clock.h>
#define DT_DRV_COMPAT nxp_sgtl5000
/* 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. STAGE 1: GLOBAL SCOPE PINCTRL ALLOCATION (MUST BE OUTSIDE FUNCTIONS) */
/* ========================================================================= */
#define DEFINE_PINCTRL_FOR_INSTANCE(inst) \
PINCTRL_DT_DEV_CONFIG_DEFINE(DT_DRV_INST(inst));
/* This macro generates the static configuration structures at the global level */
DT_INST_FOREACH_STATUS_OKAY(DEFINE_PINCTRL_FOR_INSTANCE)
/* ========================================================================= */
/* 2. STAGE 2: CLOCK CONTROL HELPER */
/* ========================================================================= */
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);
}
}
/* ========================================================================= */
/* 3. STAGE 3: EARLY INITIALIZATION LOOP */
/* ========================================================================= */
/* Note: There is NO "PINCTRL_DT_DEV_CONFIG_DEFINE" inside this runtime macro! */
#define CONFIGURE_MCLK_FOR_INSTANCE(inst) \
do { \
/* Secure a reference to the globally defined pinctrl memory block */ \
const struct pinctrl_dev_config *pcfg = \
PINCTRL_DT_DEV_CONFIG_GET(DT_DRV_INST(inst)); \
\
/* 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)
{
/* Iterate and apply the runtime configuration to all active codecs */
DT_INST_FOREACH_STATUS_OKAY(CONFIGURE_MCLK_FOR_INSTANCE)
return 0;
}
/* Register execution during the PRE_KERNEL_2 boot phase */
SYS_INIT(sgtl5000_global_force_mclk_init, PRE_KERNEL_2, 50);