Загрузка данных


#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);