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


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