soc: nxp: kinetis: ke1xz: add LPFLL clock support to SCG

LPFLL (soc: scg: "lpfll_clk") clock source can be now selected
in KE1xz Device tree (nxp_ke1xz.dtsi., board.dts or overlay)
Tested on boards: frdm_ke15z, frdm_ke17z, frdm_ke17z512

Signed-off-by: Michael Galda <michael.galda@nxp.com>
Signed-off-by: Hake Huang <hake.huang@nxp.com>
This commit is contained in:
Hake Huang
2025-11-07 20:25:45 +08:00
committed by Anas Nashif
parent 3c87d0862b
commit 68937acbb8
3 changed files with 151 additions and 85 deletions

View File

@@ -11,6 +11,14 @@ config SOC_SERIES_KE1XZ
config SOC_SERIES
default "ke1xz" if SOC_SERIES_KE1XZ
config SOC_MKE15Z4
bool
select SOC_SERIES_KE1XZ
config SOC_MKE16Z4
bool
select SOC_SERIES_KE1XZ
config SOC_MKE15Z7
bool
select SOC_SERIES_KE1XZ
@@ -24,10 +32,30 @@ config SOC_MKE17Z9
select SOC_SERIES_KE1XZ
config SOC
default "mke15z4" if SOC_MKE15Z4
default "mke16z4" if SOC_MKE16Z4
default "mke15z7" if SOC_MKE15Z7
default "mke17z7" if SOC_MKE17Z7
default "mke17z9" if SOC_MKE17Z9
config SOC_PART_NUMBER_MKE15Z64VFP4
bool
config SOC_PART_NUMBER_MKE15Z64VLD4
bool
config SOC_PART_NUMBER_MKE15Z64VLF4
bool
config SOC_PART_NUMBER_MKE16Z64VFP4
bool
config SOC_PART_NUMBER_MKE16Z64VLD4
bool
config SOC_PART_NUMBER_MKE16Z64VLF4
bool
config SOC_PART_NUMBER_MKE15Z128VLL7
bool
@@ -65,6 +93,12 @@ config SOC_PART_NUMBER_MKE17Z512VLL9
bool
config SOC_PART_NUMBER
default "MKE15Z64VFP4" if SOC_PART_NUMBER_MKE15Z64VFP4
default "MKE15Z64VLD4" if SOC_PART_NUMBER_MKE15Z64VLD4
default "MKE15Z64VLF4" if SOC_PART_NUMBER_MKE15Z64VLF4
default "MKE16Z64VFP4" if SOC_PART_NUMBER_MKE16Z64VFP4
default "MKE16Z64VLD4" if SOC_PART_NUMBER_MKE16Z64VLD4
default "MKE16Z64VLF4" if SOC_PART_NUMBER_MKE16Z64VLF4
default "MKE15Z128VLL7" if SOC_PART_NUMBER_MKE15Z128VLL7
default "MKE15Z128VLH7" if SOC_PART_NUMBER_MKE15Z128VLH7
default "MKE15Z256VLL7" if SOC_PART_NUMBER_MKE15Z256VLL7

View File

@@ -15,140 +15,170 @@
#include <fsl_clock.h>
#include <cmsis_core.h>
#define ASSERT_WITHIN_RANGE(val, min, max, str) \
BUILD_ASSERT(val >= min && val <= max, str)
#define ASSERT_WITHIN_RANGE(val, min, max, str) BUILD_ASSERT(val >= min && val <= max, str)
#define ASSERT_ASYNC_CLK_DIV_VALID(val, str) \
BUILD_ASSERT(val == 0 || val == 1 || val == 2 || val == 4 || \
val == 8 || val == 16 || val == 2 || val == 64, str)
#define ASSERT_ASYNC_CLK_DIV_VALID(val, str) \
BUILD_ASSERT(val == 0 || val == 1 || val == 2 || val == 4 || val == 8 || val == 16 || \
val == 2 || val == 64, \
str)
#define TO_SYS_CLK_DIV(val) _DO_CONCAT(kSCG_SysClkDivBy, val)
#define kSCG_AsyncClkDivBy0 kSCG_AsyncClkDisable
#define kSCG_AsyncClkDivBy0 kSCG_AsyncClkDisable
#define TO_ASYNC_CLK_DIV(val) _DO_CONCAT(kSCG_AsyncClkDivBy, val)
#define SCG_CLOCK_NODE(name) DT_CHILD(DT_INST(0, nxp_kinetis_scg), name)
#define SCG_CLOCK_DIV(name) DT_PROP(SCG_CLOCK_NODE(name), clock_div)
#define SCG_CLOCK_DIV(name) DT_PROP(SCG_CLOCK_NODE(name), clock_div)
/* System Clock configuration */
ASSERT_WITHIN_RANGE(SCG_CLOCK_DIV(bus_clk), 2, 8,
"Invalid SCG bus clock divider value");
ASSERT_WITHIN_RANGE(SCG_CLOCK_DIV(core_clk), 1, 16,
"Invalid SCG core clock divider value");
ASSERT_WITHIN_RANGE(SCG_CLOCK_DIV(bus_clk), 2, 8, "Invalid SCG bus clock divider value");
ASSERT_WITHIN_RANGE(SCG_CLOCK_DIV(core_clk), 1, 16, "Invalid SCG core clock divider value");
static const scg_sys_clk_config_t scg_sys_clk_config = {
.divSlow = TO_SYS_CLK_DIV(SCG_CLOCK_DIV(bus_clk)),
.divCore = TO_SYS_CLK_DIV(SCG_CLOCK_DIV(core_clk)),
#if DT_SAME_NODE(DT_CLOCKS_CTLR(SCG_CLOCK_NODE(core_clk)), SCG_CLOCK_NODE(sirc_clk))
.src = kSCG_SysClkSrcSirc,
.src = kSCG_SysClkSrcSirc,
#elif DT_SAME_NODE(DT_CLOCKS_CTLR(SCG_CLOCK_NODE(core_clk)), SCG_CLOCK_NODE(firc_clk))
.src = kSCG_SysClkSrcFirc,
.src = kSCG_SysClkSrcFirc,
#elif DT_SAME_NODE(DT_CLOCKS_CTLR(SCG_CLOCK_NODE(core_clk)), SCG_CLOCK_NODE(lpfll_clk))
.src = kSCG_SysClkSrcLpFll,
#elif DT_SAME_NODE(DT_CLOCKS_CTLR(SCG_CLOCK_NODE(core_clk)), SCG_CLOCK_NODE(sosc_clk))
.src = kSCG_SysClkSrcSysOsc,
#else
#error Invalid SCG core clock selected
#endif
};
/* Slow Internal Reference Clock (SIRC) configuration */
ASSERT_ASYNC_CLK_DIV_VALID(SCG_CLOCK_DIV(sircdiv2_clk),
"Invalid SCG SIRC divider 2 value");
ASSERT_ASYNC_CLK_DIV_VALID(SCG_CLOCK_DIV(sircdiv2_clk), "Invalid SCG SIRC divider 2 value");
static const scg_sirc_config_t scg_sirc_config = {
.enableMode = kSCG_SircEnable,
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(sircdiv2_clk)),
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(sircdiv2_clk)),
#if MHZ(2) == DT_PROP(SCG_CLOCK_NODE(sirc_clk), clock_frequency)
.range = kSCG_SircRangeLow
.range = kSCG_SircRangeLow
#elif MHZ(8) == DT_PROP(SCG_CLOCK_NODE(sirc_clk), clock_frequency)
.range = kSCG_SircRangeHigh
.range = kSCG_SircRangeHigh
#else
#error Invalid SCG SIRC clock frequency
#endif
};
/* Fast Internal Reference Clock (FIRC) configuration */
ASSERT_ASYNC_CLK_DIV_VALID(SCG_CLOCK_DIV(fircdiv2_clk),
"Invalid SCG FIRC divider 2 value");
ASSERT_ASYNC_CLK_DIV_VALID(SCG_CLOCK_DIV(fircdiv2_clk), "Invalid SCG FIRC divider 2 value");
static const scg_firc_config_t scg_firc_config = {
.enableMode = kSCG_FircEnable,
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(fircdiv2_clk)), /* b20253 */
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(fircdiv2_clk)),
#if MHZ(48) == DT_PROP(SCG_CLOCK_NODE(firc_clk), clock_frequency)
.range = kSCG_FircRange48M,
.range = kSCG_FircRange48M,
#elif MHZ(52) == DT_PROP(SCG_CLOCK_NODE(firc_clk), clock_frequency)
.range = kSCG_FircRange52M,
.range = kSCG_FircRange52M,
#elif MHZ(56) == DT_PROP(SCG_CLOCK_NODE(firc_clk), clock_frequency)
.range = kSCG_FircRange56M,
.range = kSCG_FircRange56M,
#elif MHZ(60) == DT_PROP(SCG_CLOCK_NODE(firc_clk), clock_frequency)
.range = kSCG_FircRange60M,
.range = kSCG_FircRange60M,
#else
#error Invalid SCG FIRC clock frequency
#endif
.trimConfig = NULL
.trimConfig = NULL};
#if DT_NODE_HAS_STATUS_OKAY(SCG_CLOCK_NODE(sosc_clk))
/* System Oscillator (SOSC) configuration */
ASSERT_ASYNC_CLK_DIV_VALID(SCG_CLOCK_DIV(soscdiv2_clk), "Invalid SCG SOSC divider 2 value");
static const scg_sosc_config_t scg_sosc_config = {
.freq = DT_PROP(SCG_CLOCK_NODE(sosc_clk), clock_frequency),
.monitorMode = kSCG_SysOscMonitorDisable,
.enableMode = kSCG_SysOscEnable | kSCG_SysOscEnableInLowPower,
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(soscdiv2_clk)),
.workMode = DT_PROP(DT_INST(0, nxp_kinetis_scg), sosc_mode)};
#endif
static const scg_lpfll_config_t scg_lpfll_config = {
.enableMode = kSCG_LpFllEnable,
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(flldiv2_clk)),
#if MHZ(48) == DT_PROP(SCG_CLOCK_NODE(lpfll_clk), clock_frequency)
.range = kSCG_LpFllRange48M,
#elif MHZ(72) == DT_PROP(SCG_CLOCK_NODE(lpfll_clk), clock_frequency)
.range = kSCG_LpFllRange72M,
#elif MHZ(96) == DT_PROP(SCG_CLOCK_NODE(lpfll_clk), clock_frequency)
.range = kSCG_LpFllRange96M,
#else
#error Invalid SCG FLL clock frequency
#endif
.trimConfig = NULL,
};
static void CLOCK_CONFIG_FircSafeConfig(const scg_firc_config_t *fircConfig)
{
scg_sys_clk_config_t curConfig;
const scg_sirc_config_t scgSircConfig = {.enableMode = kSCG_SircEnable,
.div2 = kSCG_AsyncClkDivBy2,
.range = kSCG_SircRangeHigh};
scg_sys_clk_config_t sysClkSafeConfigSource = {
.divSlow = kSCG_SysClkDivBy4, /* Slow clock divider */
.divCore = kSCG_SysClkDivBy1, /* Core clock divider */
.src = kSCG_SysClkSrcSirc /* System clock source */
};
/* Init Sirc. */
CLOCK_InitSirc(&scgSircConfig);
/* Change to use SIRC as system clock source to prepare to change FIRCCFG register. */
CLOCK_SetRunModeSysClkConfig(&sysClkSafeConfigSource);
/* Wait for clock source switch finished. */
do {
CLOCK_GetCurSysClkConfig(&curConfig);
} while (curConfig.src != sysClkSafeConfigSource.src);
/* Init Firc. */
CLOCK_InitFirc(fircConfig);
/* Change back to use FIRC as system clock source in order to configure SIRC if needed. */
sysClkSafeConfigSource.src = kSCG_SysClkSrcFirc;
CLOCK_SetRunModeSysClkConfig(&sysClkSafeConfigSource);
/* Wait for clock source switch finished. */
do {
CLOCK_GetCurSysClkConfig(&curConfig);
} while (curConfig.src != sysClkSafeConfigSource.src);
}
#define CLOCK_SETUP_ENTRY(node_label, clock_type) \
IF_ENABLED(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(node_label)), ( \
CLOCK_SetIpSrc(clock_type, DT_CLOCKS_CELL(DT_NODELABEL(node_label), ip_source)); \
))
#define CLOCK_ENABLE_ENTRY(node_label, clock_type) \
IF_ENABLED(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(node_label)), ( \
CLOCK_EnableClock(clock_type); \
))
__weak void clk_init(void)
{
const scg_sys_clk_config_t scg_sys_clk_config_safe = {
.divSlow = kSCG_SysClkDivBy4,
.divCore = kSCG_SysClkDivBy1,
.src = kSCG_SysClkSrcSirc
};
scg_sys_clk_config_t current;
scg_sys_clk_config_t current = {0};
/* Configure SIRC */
#if DT_NODE_HAS_STATUS_OKAY(SCG_CLOCK_NODE(sosc_clk))
/* Init SOSC according to board configuration. */
CLOCK_InitSysOsc(&scg_sosc_config);
CLOCK_SetXtal0Freq(scg_sosc_config.freq);
#endif
CLOCK_CONFIG_FircSafeConfig(&scg_firc_config);
CLOCK_InitSirc(&scg_sirc_config);
/* Temporary switch to safe SIRC in order to configure FIRC */
CLOCK_SetRunModeSysClkConfig(&scg_sys_clk_config_safe);
do {
CLOCK_GetCurSysClkConfig(&current);
} while (current.src != scg_sys_clk_config_safe.src);
CLOCK_InitFirc(&scg_firc_config);
/* Only RUN mode supported for now */
CLOCK_InitLpFll(&scg_lpfll_config);
CLOCK_SetRunModeSysClkConfig(&scg_sys_clk_config);
do {
CLOCK_GetCurSysClkConfig(&current);
} while (current.src != scg_sys_clk_config.src);
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpuart0))
CLOCK_SetIpSrc(kCLOCK_Lpuart0,
DT_CLOCKS_CELL(DT_NODELABEL(lpuart0), ip_source));
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpuart1))
CLOCK_SetIpSrc(kCLOCK_Lpuart1,
DT_CLOCKS_CELL(DT_NODELABEL(lpuart1), ip_source));
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpuart2))
CLOCK_SetIpSrc(kCLOCK_Lpuart2,
DT_CLOCKS_CELL(DT_NODELABEL(lpuart2), ip_source));
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpi2c0))
CLOCK_SetIpSrc(kCLOCK_Lpi2c0,
DT_CLOCKS_CELL(DT_NODELABEL(lpi2c0), ip_source));
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpi2c1))
CLOCK_SetIpSrc(kCLOCK_Lpi2c1,
DT_CLOCKS_CELL(DT_NODELABEL(lpi2c1), ip_source));
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexio))
CLOCK_SetIpSrc(kCLOCK_Flexio0,
DT_CLOCKS_CELL(DT_NODELABEL(flexio), ip_source));
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpspi0))
CLOCK_SetIpSrc(kCLOCK_Lpspi0,
DT_CLOCKS_CELL(DT_NODELABEL(lpspi0), ip_source));
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpspi1))
CLOCK_SetIpSrc(kCLOCK_Lpspi1,
DT_CLOCKS_CELL(DT_NODELABEL(lpspi1), ip_source));
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(adc0))
CLOCK_SetIpSrc(kCLOCK_Adc0,
DT_CLOCKS_CELL(DT_NODELABEL(adc0), ip_source));
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ewm0))
CLOCK_EnableClock(kCLOCK_Ewm0);
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpit0))
CLOCK_SetIpSrc(kCLOCK_Lpit0,
DT_CLOCKS_CELL(DT_NODELABEL(lpit0), ip_source));
#endif
/* Clock configuration table */
CLOCK_SETUP_ENTRY(lpuart0, kCLOCK_Lpuart0)
CLOCK_SETUP_ENTRY(lpuart1, kCLOCK_Lpuart1)
CLOCK_SETUP_ENTRY(lpuart2, kCLOCK_Lpuart2)
CLOCK_SETUP_ENTRY(lpi2c0, kCLOCK_Lpi2c0)
CLOCK_SETUP_ENTRY(lpi2c1, kCLOCK_Lpi2c1)
CLOCK_SETUP_ENTRY(flexio, kCLOCK_Flexio0)
CLOCK_SETUP_ENTRY(lpspi0, kCLOCK_Lpspi0)
CLOCK_SETUP_ENTRY(lpspi1, kCLOCK_Lpspi1)
CLOCK_SETUP_ENTRY(adc0, kCLOCK_Adc0)
CLOCK_SETUP_ENTRY(lpit0, kCLOCK_Lpit0)
CLOCK_ENABLE_ENTRY(ewm0, kCLOCK_Ewm0)
}
void soc_early_init_hook(void)

View File

@@ -31,7 +31,9 @@ family:
- name: mkv58f24
- name: ke1xz
socs:
- name: mke15z4
- name: mke15z7
- name: mke16z4
- name: mke17z7
- name: mke17z9
- name: k32lx