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
25class [[deprecated("Use ClockMcuxpressoFroSource instead")]]
26ClockMcuxpressoFro final : 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 public:
53 constexpr ClockMcuxpressoFroSource() = default;
54
55 private:
56 Status DoEnable() final {
57 POWER_DisablePD(kPDRUNCFG_PD_FFRO);
58 return OkStatus();
59 }
60
61 Status DoDisable() final {
62 POWER_EnablePD(kPDRUNCFG_PD_FFRO);
63 return OkStatus();
64 }
65};
66
69 : public DependentElement<ElementNonBlockingCannotFail> {
70 public:
72 clock_fro_output_en_t fro_output)
74 fro_output_(fro_output) {}
75
76 private:
77 Status DoEnable() final {
78 CLOCK_EnableFroClk(CLKCTL0->FRODIVOEN | fro_output_);
79 return OkStatus();
80 }
81
82 Status DoDisable() final {
83 CLOCK_EnableFroClk(CLKCTL0->FRODIVOEN & ~fro_output_);
84 return OkStatus();
85 }
86
87 const uint32_t fro_output_;
88};
89
92 : public ClockSource<ElementNonBlockingCannotFail> {
93 private:
95 Status DoEnable() final {
96 // Power up the 1MHz low power oscillator power domain.
97 POWER_DisablePD(kPDRUNCFG_PD_LPOSC);
98 // POWER_ApplyPD() is not necessary for LPOSC_PD.
99
100 // Wait for the low power oscillator to stabilize.
101 CLOCK_EnableLpOscClk();
102 return OkStatus();
103 }
104
107 // Power down the 1MHz low power oscillator power domain.
108 POWER_EnablePD(kPDRUNCFG_PD_LPOSC);
109 // POWER_ApplyPD() is not necessary for LPOSC_PD.
110 return OkStatus();
111 }
112};
113
118template <typename ElementType>
119class ClockMcuxpressoMclk final : public DependentElement<ElementType> {
120 public:
123 template <typename SourceType>
124 constexpr ClockMcuxpressoMclk(SourceType& source, uint32_t frequency)
125 : DependentElement<ElementType>(source), frequency_(frequency) {}
126
127 private:
129 Status DoEnable() final {
130 // Set global that stores external MCLK IN clock frequency.
131 CLOCK_SetMclkFreq(frequency_);
132 return OkStatus();
133 }
134
137 // Set global that stores external MCLK IN clock frequency to zero.
138 CLOCK_SetMclkFreq(0);
139 return OkStatus();
140 }
141
143 uint32_t frequency_;
144};
145
150
155
161template <typename ElementType>
162class ClockMcuxpressoClkIn final : public DependentElement<ElementType> {
163 public:
166 template <typename SourceType>
167 constexpr ClockMcuxpressoClkIn(SourceType& source, uint32_t frequency)
168 : DependentElement<ElementType>(source), frequency_(frequency) {}
169
170 private:
172 Status DoEnable() final {
173 // Set global that stores external CLK IN pin clock frequency.
174 CLOCK_SetClkinFreq(frequency_);
175
176 // OSC clock source selector ClkIn.
177 const uint8_t kCLOCK_OscClkIn = CLKCTL0_SYSOSCBYPASS_SEL(1);
178 CLKCTL0->SYSOSCBYPASS = kCLOCK_OscClkIn;
179 return OkStatus();
180 }
181
184 // Set global that stores external CLK IN pin clock frequency to zero.
185 CLOCK_SetClkinFreq(0);
186
187 // Set OSC clock source selector None, which gates output to reduce power.
188 const uint8_t kCLOCK_OscNone = CLKCTL0_SYSOSCBYPASS_SEL(7);
189 CLKCTL0->SYSOSCBYPASS = kCLOCK_OscNone;
190 return OkStatus();
191 }
192
194 uint32_t frequency_;
195};
196
201
206
211template <typename ElementType>
212class ClockMcuxpressoFrg final : public DependentElement<ElementType> {
213 public:
215 template <typename SourceType>
216 constexpr ClockMcuxpressoFrg(SourceType& source,
217 const clock_frg_clk_config_t& config)
218 : DependentElement<ElementType>(source), config_(config) {}
219
220 private:
221 // FRG clock source selector None, which gates output to reduce power.
222 // The None source selector is not defined in the SDK.
223 const uint8_t kCLOCK_FrgNone = 7;
224
226 Status DoEnable() final {
227 CLOCK_SetFRGClock(&config_);
228 return OkStatus();
229 }
230
233 clock_frg_clk_config_t disable_config = config_;
234 disable_config.sfg_clock_src =
235 static_cast<decltype(disable_config.sfg_clock_src)>(kCLOCK_FrgNone);
236 CLOCK_SetFRGClock(&disable_config);
237 return OkStatus();
238 }
239
241 const clock_frg_clk_config_t config_;
242};
243
246
250
255template <typename ElementType>
256class ClockMcuxpressoSelector : public DependentElement<ElementType> {
257 public:
261 template <typename SourceType>
262 constexpr ClockMcuxpressoSelector(SourceType& source,
263 clock_attach_id_t selector_enable,
264 clock_attach_id_t selector_disable)
265 : DependentElement<ElementType>(source),
266 selector_enable_(selector_enable),
267 selector_disable_(selector_disable) {}
268
269 private:
271 Status DoEnable() final {
272 CLOCK_AttachClk(selector_enable_);
273 return OkStatus();
274 }
275
278 CLOCK_AttachClk(selector_disable_);
279 return OkStatus();
280 }
281
283 clock_attach_id_t selector_enable_;
285 clock_attach_id_t selector_disable_;
286};
287
291
296
301template <typename ElementType>
302class ClockMcuxpressoDivider final : public ClockDividerElement<ElementType> {
303 public:
306 template <typename SourceType>
307 constexpr ClockMcuxpressoDivider(SourceType& source,
308 clock_div_name_t divider_name,
309 uint32_t divider)
310 : ClockDividerElement<ElementType>(source, divider),
311 divider_name_(divider_name) {}
312
313 private:
315 Status DoEnable() final {
316 CLOCK_SetClkDiv(divider_name_, this->divider());
317 return OkStatus();
318 }
319
321 clock_div_name_t divider_name_;
322};
323
326
331
343template <typename ElementType>
344class ClockMcuxpressoAudioPll : public DependentElement<ElementType> {
345 public:
347 template <typename SourceType>
348 constexpr ClockMcuxpressoAudioPll(SourceType& source,
349 const clock_audio_pll_config_t& config,
350 uint8_t audio_pfd_divider)
351 : DependentElement<ElementType>(source),
352 config_(&config),
353 audio_pfd_divider_(audio_pfd_divider) {}
354
356 template <typename SourceType>
357 constexpr ClockMcuxpressoAudioPll(SourceType& source,
358 audio_pll_src_t bypass_source)
359 : DependentElement<ElementType>(source), bypass_source_(bypass_source) {}
360
361 private:
364 Status DoEnable() override {
365 // If `config_` is specified, the PLL should be enabled and the phase
366 // fractional divider PFD0 needs to get configured, otherwise the PLL
367 // operates in bypass mode.
368 if (config_ != nullptr) {
369 // Configure Audio PLL clock source.
370 CLOCK_InitAudioPll(config_);
371 CLOCK_InitAudioPfd(kCLOCK_Pfd0, audio_pfd_divider_);
372 } else {
373 // PLL operates in bypass mode.
374 CLKCTL1->AUDIOPLL0CLKSEL = bypass_source_;
375 CLKCTL1->AUDIOPLL0CTL0 |= CLKCTL1_AUDIOPLL0CTL0_BYPASS_MASK;
376 }
377 return OkStatus();
378 }
379
381 Status DoDisable() override {
382 if (config_ != nullptr) {
383 // Clock gate the phase fractional divider PFD0.
384 CLOCK_DeinitAudioPfd(kCLOCK_Pfd0);
385 }
386
387 // Power down Audio PLL
388 CLOCK_DeinitAudioPll();
389 return OkStatus();
390 }
391
393 const clock_audio_pll_config_t* config_ = nullptr;
394
396 const uint8_t audio_pfd_divider_ = 0;
397
399 const audio_pll_src_t bypass_source_ = kCLOCK_AudioPllNone;
400};
401
413template <typename ElementType>
414class ClockMcuxpressoSysPll : public DependentElement<ElementType> {
415 public:
417 template <typename SourceType>
418 constexpr ClockMcuxpressoSysPll(SourceType& source,
419 const clock_sys_pll_config_t& config,
420 uint8_t sys_pfd0_divider,
421 uint8_t sys_pfd1_divider,
422 uint8_t sys_pfd2_divider,
423 uint8_t sys_pfd3_divider)
424 : DependentElement<ElementType>(source),
425 config_(&config),
426 sys_pfd0_divider_(sys_pfd0_divider),
427 sys_pfd1_divider_(sys_pfd1_divider),
428 sys_pfd2_divider_(sys_pfd2_divider),
429 sys_pfd3_divider_(sys_pfd3_divider) {}
430
432 template <typename SourceType>
433 constexpr ClockMcuxpressoSysPll(SourceType& source,
434 sys_pll_src_t bypass_source)
435 : DependentElement<ElementType>(source), bypass_source_(bypass_source) {}
436
437 private:
440 Status DoEnable() override {
441 // If `config_` is specified, the PLL should be enabled and the phase
442 // fractional divider PFD0 needs to get configured, otherwise the PLL
443 // operates in bypass mode.
444 if (config_ != nullptr) {
445 // Configure Sys PLL clock source.
446 CLOCK_InitSysPll(config_);
447
448 if (sys_pfd0_divider_ != 0) {
449 CLOCK_InitSysPfd(kCLOCK_Pfd0, sys_pfd0_divider_);
450 }
451 if (sys_pfd1_divider_ != 0) {
452 CLOCK_InitSysPfd(kCLOCK_Pfd1, sys_pfd1_divider_);
453 }
454 if (sys_pfd2_divider_ != 0) {
455 CLOCK_InitSysPfd(kCLOCK_Pfd2, sys_pfd2_divider_);
456 }
457 if (sys_pfd3_divider_ != 0) {
458 CLOCK_InitSysPfd(kCLOCK_Pfd3, sys_pfd3_divider_);
459 }
460 } else {
461 // PLL operates in bypass mode.
462 CLKCTL0->SYSPLL0CLKSEL = bypass_source_;
463 CLKCTL0->SYSPLL0CTL0 |= CLKCTL0_SYSPLL0CTL0_BYPASS_MASK;
464 }
465 return OkStatus();
466 }
467
469 Status DoDisable() override {
470 if (config_ != nullptr) {
471 // Clock gate all the phase fractional divider PFD.
472 CLOCK_DeinitSysPfd(kCLOCK_Pfd0);
473 CLOCK_DeinitSysPfd(kCLOCK_Pfd1);
474 CLOCK_DeinitSysPfd(kCLOCK_Pfd2);
475 CLOCK_DeinitSysPfd(kCLOCK_Pfd3);
476 }
477
478 // Power down Sys PLL
479 CLOCK_DeinitSysPll();
480 return OkStatus();
481 }
482
484 const clock_sys_pll_config_t* config_ = nullptr;
485
487 const uint8_t sys_pfd0_divider_ = 0;
488 const uint8_t sys_pfd1_divider_ = 0;
489 const uint8_t sys_pfd2_divider_ = 0;
490 const uint8_t sys_pfd3_divider_ = 0;
491
493 const sys_pll_src_t bypass_source_ = kCLOCK_SysPllNone;
494};
495
499
504
507
512
517template <typename ElementType>
518class ClockMcuxpressoRtc final : public DependentElement<ElementType> {
519 public:
522 template <typename SourceType>
523 constexpr ClockMcuxpressoRtc(SourceType& source)
524 : DependentElement<ElementType>(source) {}
525
526 private:
528 Status DoEnable() final {
529 // Enable 32kHZ output of RTC oscillator.
530 CLOCK_EnableOsc32K(true);
531 return OkStatus();
532 }
533
536 // Disable 32KHz output of RTC oscillator.
537 CLOCK_EnableOsc32K(false);
538 return OkStatus();
539 }
540};
541
546
551
558template <typename ElementType>
559class ClockMcuxpressoClockIp final : public DependentElement<ElementType> {
560 public:
563 template <typename SourceType>
564 constexpr ClockMcuxpressoClockIp(SourceType& source, clock_ip_name_t clock)
565 : DependentElement<ElementType>(source), clock_(clock) {}
566
567 private:
569 Status DoEnable() final {
570 CLOCK_EnableClock(clock_);
571 return OkStatus();
572 }
573
576 CLOCK_DisableClock(clock_);
577 return OkStatus();
578 }
579
580 clock_ip_name_t clock_;
581};
582
587
592} // namespace pw::clock_tree
Definition: status.h:120
Definition: clock_tree.h:471
Definition: clock_tree.h:344
Definition: clock_tree.h:162
Definition: clock_tree.h:559
Definition: clock_tree.h:302
Definition: clock_tree.h:212
FRO divider elements.
Definition: clock_tree.h:69
Class implementing an FRO clock source.
Definition: clock_tree.h:26
Class implementing the FRO clock source.
Definition: clock_tree.h:51
Class implementing the low power oscillator clock source.
Definition: clock_tree.h:92
Definition: clock_tree.h:119
Definition: clock_tree.h:518
Definition: clock_tree.h:256
Definition: clock_tree.h:414
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:433
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:348
Status DoDisable() final
Disable low power oscillator.
Definition: clock_tree.h:106
Status DoDisable() final
Disable 32 kHz RTS oscillator.
Definition: clock_tree.h:535
Status DoEnable() final
Enable low power oscillator.
Definition: clock_tree.h:95
Status DoEnable() final
Enable selector.
Definition: clock_tree.h:271
constexpr ClockMcuxpressoClkIn(SourceType &source, uint32_t frequency)
Definition: clock_tree.h:167
Status DoDisable() final
Definition: clock_tree.h:61
constexpr ClockMcuxpressoSelector(SourceType &source, clock_attach_id_t selector_enable, clock_attach_id_t selector_disable)
Definition: clock_tree.h:262
constexpr ClockMcuxpressoRtc(SourceType &source)
Definition: clock_tree.h:523
Status DoEnable() final
Enable the clock.
Definition: clock_tree.h:569
Status DoDisable() final
Disable the clock.
Definition: clock_tree.h:575
Status DoEnable() final
Set the divider configuration.
Definition: clock_tree.h:315
constexpr ClockMcuxpressoMclk(SourceType &source, uint32_t frequency)
Definition: clock_tree.h:124
Status DoEnable() final
Set MCLK IN clock frequency.
Definition: clock_tree.h:129
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:418
Status DoDisable() override
Disables the Sys PLL logic.
Definition: clock_tree.h:469
Status DoEnable() override
Definition: clock_tree.h:364
Status DoDisable() final
Disable selector.
Definition: clock_tree.h:277
constexpr ClockMcuxpressoDivider(SourceType &source, clock_div_name_t divider_name, uint32_t divider)
Definition: clock_tree.h:307
constexpr ClockMcuxpressoClockIp(SourceType &source, clock_ip_name_t clock)
Definition: clock_tree.h:564
constexpr ClockMcuxpressoFro(clock_fro_output_en_t fro_output)
Constructor specifying the FRO divider output to manage.
Definition: clock_tree.h:29
Status DoEnable() final
Function called when the clock tree element needs to get enabled.
Definition: clock_tree.h:77
Status DoEnable() final
Function called when the clock tree element needs to get enabled.
Definition: clock_tree.h:56
Status DoEnable() override
Definition: clock_tree.h:440
Status DoEnable() final
Enable 32 kHz RTC oscillator.
Definition: clock_tree.h:528
constexpr ClockMcuxpressoAudioPll(SourceType &source, audio_pll_src_t bypass_source)
Constructor to place the Audio PLL into bypass mode.
Definition: clock_tree.h:357
Status DoEnable() final
Set CLK IN clock frequency.
Definition: clock_tree.h:172
Status DoDisable() final
Disable this FRO divider.
Definition: clock_tree.h:40
Status DoDisable() final
Disable FRG configuration.
Definition: clock_tree.h:232
Status DoDisable() override
Disables the audio PLL logic.
Definition: clock_tree.h:381
Status DoEnable() final
Enable FRG configuration.
Definition: clock_tree.h:226
Status DoDisable() final
Set MCLK IN clock frequency to 0 Hz.
Definition: clock_tree.h:136
Status DoDisable() final
Set CLK IN clock frequency to 0 Hz.
Definition: clock_tree.h:183
Status DoDisable() final
Definition: clock_tree.h:82
constexpr ClockMcuxpressoFrg(SourceType &source, const clock_frg_clk_config_t &config)
Constructor specifying the source clock and FRG configuration.
Definition: clock_tree.h:216
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