Загрузка данных
#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);