Skip to content

Commit 807cce3

Browse files
committed
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>
1 parent 366d45f commit 807cce3

File tree

5 files changed

+105
-23
lines changed

5 files changed

+105
-23
lines changed

boards/nxp/frdm_ke17z512/frdm_ke17z512.dts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116

117117
&scg {
118118
bus_clk {
119-
clock-div = <2>;
119+
clock-div = <4>;
120120
};
121121
};
122122

drivers/clock_control/clock_control_mcux_scg.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static int mcux_scg_get_rate(const struct device *dev,
6969
break;
7070
#endif /* (defined(FSL_FEATURE_SCG_HAS_SPLL) && FSL_FEATURE_SCG_HAS_SPLL) */
7171
#if (defined(FSL_FEATURE_SCG_HAS_LPFLL) && FSL_FEATURE_SCG_HAS_LPFLL)
72-
case KINETIS_SCG_SPLL_CLK:
72+
case KINETIS_SCG_LPFLL_CLK:
7373
clock_name = kCLOCK_ScgLpFllClk;
7474
break;
7575
#endif /* (defined(FSL_FEATURE_SCG_HAS_LPFLL) && FSL_FEATURE_SCG_HAS_LPFLL) */
@@ -136,6 +136,8 @@ static int mcux_scg_init(const struct device *dev)
136136
CLOCK_SetClkOutSel(kClockClkoutSelFirc);
137137
#elif DT_SAME_NODE(DT_CLOCKS_CTLR(MCUX_SCG_CLOCK_NODE(clkout_clk)), MCUX_SCG_CLOCK_NODE(spll_clk))
138138
CLOCK_SetClkOutSel(kClockClkoutSelSysPll);
139+
#elif DT_SAME_NODE(DT_CLOCKS_CTLR(MCUX_SCG_CLOCK_NODE(clkout_clk)), MCUX_SCG_CLOCK_NODE(lpfll_clk))
140+
CLOCK_SetClkOutSel(kClockClkoutSelSysLpfll);
139141
#else
140142
#error Unsupported SCG clkout clock source
141143
#endif

dts/arm/nxp/nxp_ke1xz.dtsi

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,16 @@
8989
#clock-cells = <0>;
9090
};
9191

92+
lpfll_clk: lpfll_clk {
93+
compatible = "fixed-clock";
94+
clock-frequency = <72000000>;
95+
#clock-cells = <0>;
96+
};
97+
9298
core_clk: core_clk {
9399
compatible = "fixed-factor-clock";
94-
clocks = <&firc_clk>;
100+
#clocks = <&firc_clk>;
101+
clocks = <&lpfll_clk>;
95102
clock-div = <1>;
96103
#clock-cells = <0>;
97104
};
@@ -116,6 +123,13 @@
116123
clock-div = <1>;
117124
#clock-cells = <0>;
118125
};
126+
127+
flldiv2_clk: flldiv2_clk {
128+
compatible = "fixed-factor-clock";
129+
clocks = <&lpfll_clk>;
130+
clock-div = <2>;
131+
#clock-cells = <0>;
132+
};
119133
};
120134

121135
pcc: pcc@40065000 {

include/zephyr/dt-bindings/clock/kinetis_scg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@
2929
#define KINETIS_SCG_FIRC_ASYNC_DIV2_CLK 13U
3030
#define KINETIS_SCG_SPLL_ASYNC_DIV1_CLK 14U
3131
#define KINETIS_SCG_SPLL_ASYNC_DIV2_CLK 15U
32+
#define KINETIS_SCG_LPFLL_CLK 16U
3233

3334
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_KINETIS_SCG_H_ */

soc/nxp/kinetis/ke1xz/soc.c

Lines changed: 85 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 NXP
2+
* Copyright 2024, 2025 NXP
33
* Copyright (c) 2019-2021 Vestas Wind Systems A/S
44
*
55
* Based on NXP k6x soc.c, which is:
@@ -43,13 +43,19 @@ static const scg_sys_clk_config_t scg_sys_clk_config = {
4343
.src = kSCG_SysClkSrcSirc,
4444
#elif DT_SAME_NODE(DT_CLOCKS_CTLR(SCG_CLOCK_NODE(core_clk)), SCG_CLOCK_NODE(firc_clk))
4545
.src = kSCG_SysClkSrcFirc,
46+
#elif DT_SAME_NODE(DT_CLOCKS_CTLR(SCG_CLOCK_NODE(core_clk)), SCG_CLOCK_NODE(lpfll_clk))
47+
.src = kSCG_SysClkSrcLpFll,
48+
#elif DT_SAME_NODE(DT_CLOCKS_CTLR(SCG_CLOCK_NODE(core_clk)), SCG_CLOCK_NODE(sosc_clk))
49+
.src = kSCG_SysClkSrcSysOsc,
50+
#else
51+
#error Invalid SCG core clock selected
4652
#endif
4753
};
4854

4955
/* Slow Internal Reference Clock (SIRC) configuration */
5056
ASSERT_ASYNC_CLK_DIV_VALID(SCG_CLOCK_DIV(sircdiv2_clk),
5157
"Invalid SCG SIRC divider 2 value");
52-
static const scg_sirc_config_t scg_sirc_config = {
58+
static scg_sirc_config_t scg_sirc_config = {
5359
.enableMode = kSCG_SircEnable,
5460
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(sircdiv2_clk)),
5561
#if MHZ(2) == DT_PROP(SCG_CLOCK_NODE(sirc_clk), clock_frequency)
@@ -66,7 +72,7 @@ ASSERT_ASYNC_CLK_DIV_VALID(SCG_CLOCK_DIV(fircdiv2_clk),
6672
"Invalid SCG FIRC divider 2 value");
6773
static const scg_firc_config_t scg_firc_config = {
6874
.enableMode = kSCG_FircEnable,
69-
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(fircdiv2_clk)), /* b20253 */
75+
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(fircdiv2_clk)),
7076
#if MHZ(48) == DT_PROP(SCG_CLOCK_NODE(firc_clk), clock_frequency)
7177
.range = kSCG_FircRange48M,
7278
#elif MHZ(52) == DT_PROP(SCG_CLOCK_NODE(firc_clk), clock_frequency)
@@ -81,31 +87,90 @@ static const scg_firc_config_t scg_firc_config = {
8187
.trimConfig = NULL
8288
};
8389

84-
__weak void clk_init(void)
90+
#if DT_NODE_HAS_STATUS_OKAY(SCG_CLOCK_NODE(sosc_clk))
91+
/* System Oscillator (SOSC) configuration */
92+
ASSERT_ASYNC_CLK_DIV_VALID(SCG_CLOCK_DIV(soscdiv2_clk)),
93+
"Invalid SCG SOSC divider 2 value");
94+
static const scg_sosc_config_t scg_sosc_config = {
95+
.freq = DT_PROP(SCG_CLOCK_NODE(sosc_clk), clock_frequency),
96+
.monitorMode = kSCG_SysOscMonitorDisable,
97+
.enableMode = kSCG_SysOscEnable | kSCG_SysOscEnableInLowPower,
98+
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(soscdiv2_clk)),
99+
.workMode = DT_PROP(DT_INST(0, nxp_kinetis_scg), sosc_mode)
100+
};
101+
#endif /* DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_scg), sosc_freq) */
102+
103+
104+
static const scg_lpfll_config_t scg_lpfll_config = {
105+
.enableMode = kSCG_LpFllEnable,
106+
.div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(flldiv2_clk)),
107+
#if MHZ(48) == DT_PROP(SCG_CLOCK_NODE(lpfll_clk), clock_frequency)
108+
.range = kSCG_LpFllRange48M,
109+
#elif MHZ(72) == DT_PROP(SCG_CLOCK_NODE(lpfll_clk), clock_frequency)
110+
.range = kSCG_LpFllRange72M,
111+
#elif MHZ(96) == DT_PROP(SCG_CLOCK_NODE(lpfll_clk), clock_frequency)
112+
.range = kSCG_LpFllRange96M,
113+
#else
114+
#error Invalid SCG FLL clock frequency
115+
#endif
116+
.trimConfig = NULL,
117+
};
118+
119+
120+
static void CLOCK_CONFIG_FircSafeConfig(const scg_firc_config_t *fircConfig)
85121
{
86-
const scg_sys_clk_config_t scg_sys_clk_config_safe = {
87-
.divSlow = kSCG_SysClkDivBy4,
88-
.divCore = kSCG_SysClkDivBy1,
89-
.src = kSCG_SysClkSrcSirc
122+
scg_sys_clk_config_t curConfig;
123+
const scg_sirc_config_t scgSircConfig = {.enableMode = kSCG_SircEnable,
124+
.div2 = kSCG_AsyncClkDivBy2,
125+
.range = kSCG_SircRangeHigh};
126+
scg_sys_clk_config_t sysClkSafeConfigSource = {
127+
.divSlow = kSCG_SysClkDivBy4, /* Slow clock divider */
128+
.divCore = kSCG_SysClkDivBy1, /* Core clock divider */
129+
.src = kSCG_SysClkSrcSirc /* System clock source */
90130
};
91-
scg_sys_clk_config_t current;
131+
/* Init Sirc. */
132+
CLOCK_InitSirc(&scgSircConfig);
133+
/* Change to use SIRC as system clock source to prepare to change FIRCCFG register. */
134+
CLOCK_SetRunModeSysClkConfig(&sysClkSafeConfigSource);
135+
/* Wait for clock source switch finished. */
136+
do {
137+
CLOCK_GetCurSysClkConfig(&curConfig);
138+
} while (curConfig.src != sysClkSafeConfigSource.src);
139+
140+
/* Init Firc. */
141+
CLOCK_InitFirc(fircConfig);
142+
/* Change back to use FIRC as system clock source in order to configure SIRC if needed. */
143+
sysClkSafeConfigSource.src = kSCG_SysClkSrcFirc;
144+
CLOCK_SetRunModeSysClkConfig(&sysClkSafeConfigSource);
145+
/* Wait for clock source switch finished. */
146+
do {
147+
CLOCK_GetCurSysClkConfig(&curConfig);
148+
} while (curConfig.src != sysClkSafeConfigSource.src);
149+
}
92150

93-
/* Configure SIRC */
94-
CLOCK_InitSirc(&scg_sirc_config);
95151

96-
/* Temporary switch to safe SIRC in order to configure FIRC */
97-
CLOCK_SetRunModeSysClkConfig(&scg_sys_clk_config_safe);
98-
do {
99-
CLOCK_GetCurSysClkConfig(&current);
100-
} while (current.src != scg_sys_clk_config_safe.src);
101-
CLOCK_InitFirc(&scg_firc_config);
152+
__weak void clk_init(void)
153+
{
154+
scg_sys_clk_config_t current;
102155

103-
/* Only RUN mode supported for now */
104-
CLOCK_SetRunModeSysClkConfig(&scg_sys_clk_config);
156+
#if DT_NODE_HAS_STATUS_OKAY(SCG_CLOCK_NODE(sosc_clk))
157+
/* Init SOSC according to board configuration. */
158+
CLOCK_InitSysOsc(&scg_sysosc_config);
159+
CLOCK_SetXtal0Freq(scg_sysosc_config.freq);
160+
#endif
161+
/* Init FIRC. */
162+
CLOCK_CONFIG_FircSafeConfig(&scg_firc_config);
163+
/* Init SIRC. */
164+
CLOCK_InitSirc(&scg_sirc_config);
165+
/* Init LPFLL. */
166+
CLOCK_InitLpFll(&scg_lpfll_config);
167+
/* Finally init the App desired clock */
168+
CLOCK_SetRunModeSysClkConfig(&scg_sys_clk_config);
105169
do {
106-
CLOCK_GetCurSysClkConfig(&current);
170+
CLOCK_GetCurSysClkConfig(&current);
107171
} while (current.src != scg_sys_clk_config.src);
108172

173+
109174
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpuart0))
110175
CLOCK_SetIpSrc(kCLOCK_Lpuart0,
111176
DT_CLOCKS_CELL(DT_NODELABEL(lpuart0), ip_source));

0 commit comments

Comments
 (0)