C/C++ API Reference
Loading...
Searching...
No Matches
clock_tree.h
1// Copyright 2024 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include "fsl_clock.h"
17#include "fsl_power.h"
18#include "pw_clock_tree/clock_tree.h"
19
20namespace pw::clock_tree {
21
23
26 : public ClockSource<ElementNonBlockingCannotFail> {
27 public:
29 constexpr ClockMcuxpressoFro(clock_fro_output_en_t fro_output)
30 : fro_output_(fro_output) {}
31
32 private:
34 Status DoEnable() final {
35 CLOCK_EnableFroClk(CLKCTL0->FRODIVOEN | fro_output_);
36 return OkStatus();
37 }
38
40 Status DoDisable() final {
41 CLOCK_EnableFroClk(CLKCTL0->FRODIVOEN & ~fro_output_);
42 return OkStatus();
43 }
44
46 const uint32_t fro_output_;
47};
48
51 : public ClockSource<ElementNonBlockingCannotFail> {
52 private:
54 Status DoEnable() final {
55 // Power up the 1MHz low power oscillator power domain.
56 POWER_DisablePD(kPDRUNCFG_PD_LPOSC);
57 // POWER_ApplyPD() is not necessary for LPOSC_PD.
58
59 // Wait for the low power oscillator to stabilize.
60 CLOCK_EnableLpOscClk();
61 return OkStatus();
62 }
63
65 Status DoDisable() final {
66 // Power down the 1MHz low power oscillator power domain.
67 POWER_EnablePD(kPDRUNCFG_PD_LPOSC);
68 // POWER_ApplyPD() is not necessary for LPOSC_PD.
69 return OkStatus();
70 }
71};
72
77template <typename ElementType>
78class ClockMcuxpressoMclk final : public DependentElement<ElementType> {
79 public:
82 template <typename SourceType>
83 constexpr ClockMcuxpressoMclk(SourceType& source, uint32_t frequency)
84 : DependentElement<ElementType>(source), frequency_(frequency) {}
85
86 private:
88 Status DoEnable() final {
89 // Set global that stores external MCLK IN clock frequency.
90 CLOCK_SetMclkFreq(frequency_);
91 return OkStatus();
92 }
93
95 Status DoDisable() final {
96 // Set global that stores external MCLK IN clock frequency to zero.
97 CLOCK_SetMclkFreq(0);
98 return OkStatus();
99 }
100
102 uint32_t frequency_;
103};
104
109
114
120template <typename ElementType>
121class ClockMcuxpressoClkIn final : public DependentElement<ElementType> {
122 public:
125 template <typename SourceType>
126 constexpr ClockMcuxpressoClkIn(SourceType& source, uint32_t frequency)
127 : DependentElement<ElementType>(source), frequency_(frequency) {}
128
129 private:
131 Status DoEnable() final {
132 // Set global that stores external CLK IN pin clock frequency.
133 CLOCK_SetClkinFreq(frequency_);
134
135 // OSC clock source selector ClkIn.
136 const uint8_t kCLOCK_OscClkIn = CLKCTL0_SYSOSCBYPASS_SEL(1);
137 CLKCTL0->SYSOSCBYPASS = kCLOCK_OscClkIn;
138 return OkStatus();
139 }
140
143 // Set global that stores external CLK IN pin clock frequency to zero.
144 CLOCK_SetClkinFreq(0);
145
146 // Set OSC clock source selector None, which gates output to reduce power.
147 const uint8_t kCLOCK_OscNone = CLKCTL0_SYSOSCBYPASS_SEL(7);
148 CLKCTL0->SYSOSCBYPASS = kCLOCK_OscNone;
149 return OkStatus();
150 }
151
153 uint32_t frequency_;
154};
155
160
165
170template <typename ElementType>
171class ClockMcuxpressoFrg final : public DependentElement<ElementType> {
172 public:
174 template <typename SourceType>
175 constexpr ClockMcuxpressoFrg(SourceType& source,
176 const clock_frg_clk_config_t& config)
177 : DependentElement<ElementType>(source), config_(config) {}
178
179 private:
180 // FRG clock source selector None, which gates output to reduce power.
181 // The None source selector is not defined in the SDK.
182 const uint8_t kCLOCK_FrgNone = 7;
183
185 Status DoEnable() final {
186 CLOCK_SetFRGClock(&config_);
187 return OkStatus();
188 }
189
192 clock_frg_clk_config_t disable_config = config_;
193 disable_config.sfg_clock_src =
194 static_cast<decltype(disable_config.sfg_clock_src)>(kCLOCK_FrgNone);
195 CLOCK_SetFRGClock(&disable_config);
196 return OkStatus();
197 }
198
200 const clock_frg_clk_config_t config_;
201};
202
205
209
214template <typename ElementType>
215class ClockMcuxpressoSelector : public DependentElement<ElementType> {
216 public:
220 template <typename SourceType>
221 constexpr ClockMcuxpressoSelector(SourceType& source,
222 clock_attach_id_t selector_enable,
223 clock_attach_id_t selector_disable)
224 : DependentElement<ElementType>(source),
225 selector_enable_(selector_enable),
226 selector_disable_(selector_disable) {}
227
228 private:
230 Status DoEnable() final {
231 CLOCK_AttachClk(selector_enable_);
232 return OkStatus();
233 }
234
237 CLOCK_AttachClk(selector_disable_);
238 return OkStatus();
239 }
240
242 clock_attach_id_t selector_enable_;
244 clock_attach_id_t selector_disable_;
245};
246
250
255
260template <typename ElementType>
261class ClockMcuxpressoDivider final : public ClockDividerElement<ElementType> {
262 public:
265 template <typename SourceType>
266 constexpr ClockMcuxpressoDivider(SourceType& source,
267 clock_div_name_t divider_name,
268 uint32_t divider)
269 : ClockDividerElement<ElementType>(source, divider),
270 divider_name_(divider_name) {}
271
272 private:
274 Status DoEnable() final {
275 CLOCK_SetClkDiv(divider_name_, this->divider());
276 return OkStatus();
277 }
278
280 clock_div_name_t divider_name_;
281};
282
285
290
302template <typename ElementType>
303class ClockMcuxpressoAudioPll : public DependentElement<ElementType> {
304 public:
306 template <typename SourceType>
307 constexpr ClockMcuxpressoAudioPll(SourceType& source,
308 const clock_audio_pll_config_t& config,
309 uint8_t audio_pfd_divider)
310 : DependentElement<ElementType>(source),
311 config_(&config),
312 audio_pfd_divider_(audio_pfd_divider) {}
313
315 template <typename SourceType>
316 constexpr ClockMcuxpressoAudioPll(SourceType& source,
317 audio_pll_src_t bypass_source)
318 : DependentElement<ElementType>(source), bypass_source_(bypass_source) {}
319
320 private:
323 Status DoEnable() override {
324 // If `config_` is specified, the PLL should be enabled and the phase
325 // fractional divider PFD0 needs to get configured, otherwise the PLL
326 // operates in bypass mode.
327 if (config_ != nullptr) {
328 // Configure Audio PLL clock source.
329 CLOCK_InitAudioPll(config_);
330 CLOCK_InitAudioPfd(kCLOCK_Pfd0, audio_pfd_divider_);
331 } else {
332 // PLL operates in bypass mode.
333 CLKCTL1->AUDIOPLL0CLKSEL = bypass_source_;
334 CLKCTL1->AUDIOPLL0CTL0 |= CLKCTL1_AUDIOPLL0CTL0_BYPASS_MASK;
335 }
336 return OkStatus();
337 }
338
340 Status DoDisable() override {
341 if (config_ != nullptr) {
342 // Clock gate the phase fractional divider PFD0.
343 CLOCK_DeinitAudioPfd(kCLOCK_Pfd0);
344 }
345
346 // Power down Audio PLL
347 CLOCK_DeinitAudioPll();
348 return OkStatus();
349 }
350
352 const clock_audio_pll_config_t* config_ = nullptr;
353
355 const uint8_t audio_pfd_divider_ = 0;
356
358 const audio_pll_src_t bypass_source_ = kCLOCK_AudioPllNone;
359};
360
372template <typename ElementType>
373class ClockMcuxpressoSysPll : public DependentElement<ElementType> {
374 public:
376 template <typename SourceType>
377 constexpr ClockMcuxpressoSysPll(SourceType& source,
378 const clock_sys_pll_config_t& config,
379 uint8_t sys_pfd0_divider,
380 uint8_t sys_pfd1_divider,
381 uint8_t sys_pfd2_divider,
382 uint8_t sys_pfd3_divider)
383 : DependentElement<ElementType>(source),
384 config_(&config),
385 sys_pfd0_divider_(sys_pfd0_divider),
386 sys_pfd1_divider_(sys_pfd1_divider),
387 sys_pfd2_divider_(sys_pfd2_divider),
388 sys_pfd3_divider_(sys_pfd3_divider) {}
389
391 template <typename SourceType>
392 constexpr ClockMcuxpressoSysPll(SourceType& source,
393 sys_pll_src_t bypass_source)
394 : DependentElement<ElementType>(source), bypass_source_(bypass_source) {}
395
396 private:
399 Status DoEnable() override {
400 // If `config_` is specified, the PLL should be enabled and the phase
401 // fractional divider PFD0 needs to get configured, otherwise the PLL
402 // operates in bypass mode.
403 if (config_ != nullptr) {
404 // Configure Sys PLL clock source.
405 CLOCK_InitSysPll(config_);
406
407 if (sys_pfd0_divider_ != 0) {
408 CLOCK_InitSysPfd(kCLOCK_Pfd0, sys_pfd0_divider_);
409 }
410 if (sys_pfd1_divider_ != 0) {
411 CLOCK_InitSysPfd(kCLOCK_Pfd1, sys_pfd1_divider_);
412 }
413 if (sys_pfd2_divider_ != 0) {
414 CLOCK_InitSysPfd(kCLOCK_Pfd2, sys_pfd2_divider_);
415 }
416 if (sys_pfd3_divider_ != 0) {
417 CLOCK_InitSysPfd(kCLOCK_Pfd3, sys_pfd3_divider_);
418 }
419 } else {
420 // PLL operates in bypass mode.
421 CLKCTL0->SYSPLL0CLKSEL = bypass_source_;
422 CLKCTL0->SYSPLL0CTL0 |= CLKCTL0_SYSPLL0CTL0_BYPASS_MASK;
423 }
424 return OkStatus();
425 }
426
428 Status DoDisable() override {
429 if (config_ != nullptr) {
430 // Clock gate all the phase fractional divider PFD.
431 CLOCK_DeinitSysPfd(kCLOCK_Pfd0);
432 CLOCK_DeinitSysPfd(kCLOCK_Pfd1);
433 CLOCK_DeinitSysPfd(kCLOCK_Pfd2);
434 CLOCK_DeinitSysPfd(kCLOCK_Pfd3);
435 }
436
437 // Power down Sys PLL
438 CLOCK_DeinitSysPll();
439 return OkStatus();
440 }
441
443 const clock_sys_pll_config_t* config_ = nullptr;
444
446 const uint8_t sys_pfd0_divider_ = 0;
447 const uint8_t sys_pfd1_divider_ = 0;
448 const uint8_t sys_pfd2_divider_ = 0;
449 const uint8_t sys_pfd3_divider_ = 0;
450
452 const sys_pll_src_t bypass_source_ = kCLOCK_SysPllNone;
453};
454
458
463
466
471
476template <typename ElementType>
477class ClockMcuxpressoRtc final : public DependentElement<ElementType> {
478 public:
481 template <typename SourceType>
482 constexpr ClockMcuxpressoRtc(SourceType& source)
483 : DependentElement<ElementType>(source) {}
484
485 private:
487 Status DoEnable() final {
488 // Enable 32kHZ output of RTC oscillator.
489 CLOCK_EnableOsc32K(true);
490 return OkStatus();
491 }
492
495 // Disable 32KHz output of RTC oscillator.
496 CLOCK_EnableOsc32K(false);
497 return OkStatus();
498 }
499};
500
505
510
517template <typename ElementType>
518class ClockMcuxpressoClockIp final : public DependentElement<ElementType> {
519 public:
522 template <typename SourceType>
523 constexpr ClockMcuxpressoClockIp(SourceType& source, clock_ip_name_t clock)
524 : DependentElement<ElementType>(source), clock_(clock) {}
525
526 private:
528 Status DoEnable() final {
529 CLOCK_EnableClock(clock_);
530 return OkStatus();
531 }
532
535 CLOCK_DisableClock(clock_);
536 return OkStatus();
537 }
538
539 clock_ip_name_t clock_;
540};
541
546
551} // namespace pw::clock_tree
Definition: status.h:120
Definition: clock_tree.h:471
Definition: clock_tree.h:303
Definition: clock_tree.h:121
Definition: clock_tree.h:518
Definition: clock_tree.h:261
Definition: clock_tree.h:171
Class implementing an FRO clock source.
Definition: clock_tree.h:26
Class implementing the low power oscillator clock source.
Definition: clock_tree.h:51
Definition: clock_tree.h:78
Definition: clock_tree.h:477
Definition: clock_tree.h:215
Definition: clock_tree.h:373
Definition: clock_tree.h:239
Definition: clock_tree.h:338
constexpr ClockMcuxpressoSysPll(SourceType &source, sys_pll_src_t bypass_source)
Constructor to place the Sys PLL into bypass mode.
Definition: clock_tree.h:392
constexpr ClockMcuxpressoAudioPll(SourceType &source, const clock_audio_pll_config_t &config, uint8_t audio_pfd_divider)
Constructor specifying the configuration for the enabled Audio PLL.
Definition: clock_tree.h:307
Status DoDisable() final
Disable low power oscillator.
Definition: clock_tree.h:65
Status DoDisable() final
Disable 32 kHz RTS oscillator.
Definition: clock_tree.h:494
Status DoEnable() final
Enable low power oscillator.
Definition: clock_tree.h:54
Status DoEnable() final
Enable selector.
Definition: clock_tree.h:230
constexpr ClockMcuxpressoClkIn(SourceType &source, uint32_t frequency)
Definition: clock_tree.h:126
constexpr ClockMcuxpressoSelector(SourceType &source, clock_attach_id_t selector_enable, clock_attach_id_t selector_disable)
Definition: clock_tree.h:221
constexpr ClockMcuxpressoRtc(SourceType &source)
Definition: clock_tree.h:482
Status DoEnable() final
Enable the clock.
Definition: clock_tree.h:528
Status DoDisable() final
Disable the clock.
Definition: clock_tree.h:534
Status DoEnable() final
Set the divider configuration.
Definition: clock_tree.h:274
constexpr ClockMcuxpressoMclk(SourceType &source, uint32_t frequency)
Definition: clock_tree.h:83
Status DoEnable() final
Set MCLK IN clock frequency.
Definition: clock_tree.h:88
constexpr ClockMcuxpressoSysPll(SourceType &source, const clock_sys_pll_config_t &config, uint8_t sys_pfd0_divider, uint8_t sys_pfd1_divider, uint8_t sys_pfd2_divider, uint8_t sys_pfd3_divider)
Constructor specifying the configuration for the enabled Sys PLL.
Definition: clock_tree.h:377
Status DoDisable() override
Disables the Sys PLL logic.
Definition: clock_tree.h:428
Status DoEnable() override
Definition: clock_tree.h:323
Status DoDisable() final
Disable selector.
Definition: clock_tree.h:236
constexpr ClockMcuxpressoDivider(SourceType &source, clock_div_name_t divider_name, uint32_t divider)
Definition: clock_tree.h:266
constexpr ClockMcuxpressoClockIp(SourceType &source, clock_ip_name_t clock)
Definition: clock_tree.h:523
constexpr ClockMcuxpressoFro(clock_fro_output_en_t fro_output)
Constructor specifying the FRO divider output to manage.
Definition: clock_tree.h:29
Status DoEnable() override
Definition: clock_tree.h:399
Status DoEnable() final
Enable 32 kHz RTC oscillator.
Definition: clock_tree.h:487
constexpr ClockMcuxpressoAudioPll(SourceType &source, audio_pll_src_t bypass_source)
Constructor to place the Audio PLL into bypass mode.
Definition: clock_tree.h:316
Status DoEnable() final
Set CLK IN clock frequency.
Definition: clock_tree.h:131
Status DoDisable() final
Disable this FRO divider.
Definition: clock_tree.h:40
Status DoDisable() final
Disable FRG configuration.
Definition: clock_tree.h:191
Status DoDisable() override
Disables the audio PLL logic.
Definition: clock_tree.h:340
Status DoEnable() final
Enable FRG configuration.
Definition: clock_tree.h:185
Status DoDisable() final
Set MCLK IN clock frequency to 0 Hz.
Definition: clock_tree.h:95
Status DoDisable() final
Set CLK IN clock frequency to 0 Hz.
Definition: clock_tree.h:142
constexpr ClockMcuxpressoFrg(SourceType &source, const clock_frg_clk_config_t &config)
Constructor specifying the source clock and FRG configuration.
Definition: clock_tree.h:175
Status DoEnable() final
Enable this FRO divider.
Definition: clock_tree.h:34
uint32_t divider() const
Get current divider value.
Definition: clock_tree.h:504
constexpr Status OkStatus()
Definition: status.h:450
Clock tree management library.
Definition: clock_tree.h:30