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


#include <zephyr/init.h>
#include <zephyr/drivers/pinctrl.h>
#include <fsl_clock.h>

/* Helper macros to extract configuration data from the Devicetree dynamically */
#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))

/**
 * @brief Dynamic hardware clock and pinmux initialisation loop for each codec instance.
 */
#define CONFIGURE_MCLK_FOR_INSTANCE(inst)                                                          \
	do {                                                                                       \
		/* 1. Extract and automatically apply the pinctrl (Pinmux) state from DTS */       \
		PINCTRL_DT_DEV_CONFIG_DEFINE(DT_DRV_INST(inst));                                   \
		const struct pinctrl_dev_config *pcfg =                                            \
			PINCTRL_DT_DEV_CONFIG_GET(DT_DRV_INST(inst));                              \
		int p_ret = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT);                      \
		if (p_ret < 0) {                                                                   \
			printk("SGTL5000 Patch Line Error: Failed to apply pinctrl for inst %d\n", \
			       inst);                                                              \
		}                                                                                  \
                                                                                                   \
		/* 2. Platform-agnostic Clock Gate Un-gating using Core SDK mappings */            \
		uint32_t base_addr = CODEC_SAI_BASE(inst);                                         \
		if (base_addr == DT_REG_ADDR(DT_NODELABEL(sai1))) {                                \
			CLOCK_EnableClock(kCLOCK_Sai1);                                            \
			CLOCK_SetMux(kCLOCK_Sai1Mux, 0);                                           \
			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);                                           \
			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);                                           \
			CLOCK_SetDiv(kCLOCK_Sai3PreDiv, 3);                                        \
			CLOCK_SetDiv(kCLOCK_Sai3Div, 7);                                           \
		}                                                                                  \
                                                                                                   \
		/* 3. Force Bit Clock Enable (BCE) to un-gate dynamic master clock routing */     \
		((I2S_Type *)base_addr)->TCSR |= I2S_TCSR_BCE_MASK;                                \
		printk("SGTL5000 Patch: Dynamic MCLK un-gated for instance %d at SAI block "      \
		       "0x%08X\n",                                                                 \
		       inst, base_addr);                                                           \
	} while (0);

static int sgtl5000_global_force_mclk_init(void)
{
	/* Iterate through all active compiled codecs and apply cross-platform logic */
	DT_INST_FOREACH_STATUS_OKAY(CONFIGURE_MCLK_FOR_INSTANCE)
	return 0;
}

/* Run at PRE_KERNEL_2 phase to unlock I2C registers before device discovery tasks */
SYS_INIT(sgtl5000_global_force_mclk_init, PRE_KERNEL_2, 50);