C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 constexpr ClockMcuxpressoMclk(ElementType& source, uint32_t frequency)
83 : DependentElement<ElementType>(source), frequency_(frequency) {}
84
85 private:
87 Status DoEnable() final {
88 // Set global that stores external MCLK IN clock frequency.
89 CLOCK_SetMclkFreq(frequency_);
90 return OkStatus();
91 }
92
94 Status DoDisable() final {
95 // Set global that stores external MCLK IN clock frequency to zero.
96 CLOCK_SetMclkFreq(0);
97 return OkStatus();
98 }
99
101 uint32_t frequency_;
102};
103
108
113
119template <typename ElementType>
120class ClockMcuxpressoClkIn final : public DependentElement<ElementType> {
121 public:
124 constexpr ClockMcuxpressoClkIn(ElementType& source, uint32_t frequency)
125 : DependentElement<ElementType>(source), frequency_(frequency) {}
126
127 private:
129 Status DoEnable() final {
130 // Set global that stores external CLK IN pin clock frequency.
131 CLOCK_SetClkinFreq(frequency_);
132
133 // OSC clock source selector ClkIn.
134 const uint8_t kCLOCK_OscClkIn = CLKCTL0_SYSOSCBYPASS_SEL(1);
135 CLKCTL0->SYSOSCBYPASS = kCLOCK_OscClkIn;
136 return OkStatus();
137 }
138
141 // Set global that stores external CLK IN pin clock frequency to zero.
142 CLOCK_SetClkinFreq(0);
143
144 // Set OSC clock source selector None, which gates output to reduce power.
145 const uint8_t kCLOCK_OscNone = CLKCTL0_SYSOSCBYPASS_SEL(7);
146 CLKCTL0->SYSOSCBYPASS = kCLOCK_OscNone;
147 return OkStatus();
148 }
149
151 uint32_t frequency_;
152};
153
158
163
168template <typename ElementType>
169class ClockMcuxpressoFrg final : public DependentElement<ElementType> {
170 public:
172 constexpr ClockMcuxpressoFrg(ElementType& source,
173 const clock_frg_clk_config_t& config)
174 : DependentElement<ElementType>(source), config_(config) {}
175
176 private:
177 // FRG clock source selector None, which gates output to reduce power.
178 // The None source selector is not defined in the SDK.
179 const uint8_t kCLOCK_FrgNone = 7;
180
182 Status DoEnable() final {
183 CLOCK_SetFRGClock(&config_);
184 return OkStatus();
185 }
186
189 clock_frg_clk_config_t disable_config = config_;
190 disable_config.sfg_clock_src =
191 static_cast<decltype(disable_config.sfg_clock_src)>(kCLOCK_FrgNone);
192 CLOCK_SetFRGClock(&disable_config);
193 return OkStatus();
194 }
195
197 const clock_frg_clk_config_t config_;
198};
199
202
206
211template <typename ElementType>
212class ClockMcuxpressoSelector : public DependentElement<ElementType> {
213 public:
217 constexpr ClockMcuxpressoSelector(ElementType& source,
218 clock_attach_id_t selector_enable,
219 clock_attach_id_t selector_disable)
220 : DependentElement<ElementType>(source),
221 selector_enable_(selector_enable),
222 selector_disable_(selector_disable) {}
223
224 private:
226 Status DoEnable() final {
227 CLOCK_AttachClk(selector_enable_);
228 return OkStatus();
229 }
230
233 CLOCK_AttachClk(selector_disable_);
234 return OkStatus();
235 }
236
238 clock_attach_id_t selector_enable_;
240 clock_attach_id_t selector_disable_;
241};
242
246
251
256template <typename ElementType>
257class ClockMcuxpressoDivider final : public ClockDividerElement<ElementType> {
258 public:
261 constexpr ClockMcuxpressoDivider(ElementType& source,
262 clock_div_name_t divider_name,
263 uint32_t divider)
264 : ClockDividerElement<ElementType>(source, divider),
265 divider_name_(divider_name) {}
266
267 private:
269 Status DoEnable() final {
270 CLOCK_SetClkDiv(divider_name_, this->divider());
271 return OkStatus();
272 }
273
275 clock_div_name_t divider_name_;
276};
277
280
285
297template <typename ElementType>
298class ClockMcuxpressoAudioPll : public DependentElement<ElementType> {
299 public:
301 constexpr ClockMcuxpressoAudioPll(ElementType& source,
302 const clock_audio_pll_config_t& config,
303 uint8_t audio_pfd_divider)
304 : DependentElement<ElementType>(source),
305 config_(&config),
306 audio_pfd_divider_(audio_pfd_divider) {}
307
309 constexpr ClockMcuxpressoAudioPll(ElementType& source,
310 audio_pll_src_t bypass_source)
311 : DependentElement<ElementType>(source), bypass_source_(bypass_source) {}
312
313 private:
316 Status DoEnable() override {
317 // If `config_` is specified, the PLL should be enabled and the phase
318 // fractional divider PFD0 needs to get configured, otherwise the PLL
319 // operates in bypass mode.
320 if (config_ != nullptr) {
321 // Configure Audio PLL clock source.
322 CLOCK_InitAudioPll(config_);
323 CLOCK_InitAudioPfd(kCLOCK_Pfd0, audio_pfd_divider_);
324 } else {
325 // PLL operates in bypass mode.
326 CLKCTL1->AUDIOPLL0CLKSEL = bypass_source_;
327 CLKCTL1->AUDIOPLL0CTL0 |= CLKCTL1_AUDIOPLL0CTL0_BYPASS_MASK;
328 }
329 return OkStatus();
330 }
331
333 Status DoDisable() override {
334 if (config_ != nullptr) {
335 // Clock gate the phase fractional divider PFD0.
336 CLOCK_DeinitAudioPfd(kCLOCK_Pfd0);
337 }
338
339 // Power down Audio PLL
340 CLOCK_DeinitAudioPll();
341 return OkStatus();
342 }
343
345 const clock_audio_pll_config_t* config_ = nullptr;
346
348 const uint8_t audio_pfd_divider_ = 0;
349
351 const audio_pll_src_t bypass_source_ = kCLOCK_AudioPllNone;
352};
353
365template <typename ElementType>
366class ClockMcuxpressoSysPll : public DependentElement<ElementType> {
367 public:
369 constexpr ClockMcuxpressoSysPll(ElementType& source,
370 const clock_sys_pll_config_t& config,
371 uint8_t sys_pfd0_divider,
372 uint8_t sys_pfd1_divider,
373 uint8_t sys_pfd2_divider,
374 uint8_t sys_pfd3_divider)
375 : DependentElement<ElementType>(source),
376 config_(&config),
377 sys_pfd0_divider_(sys_pfd0_divider),
378 sys_pfd1_divider_(sys_pfd1_divider),
379 sys_pfd2_divider_(sys_pfd2_divider),
380 sys_pfd3_divider_(sys_pfd3_divider) {}
381
383 constexpr ClockMcuxpressoSysPll(ElementType& source,
384 sys_pll_src_t bypass_source)
385 : DependentElement<ElementType>(source), bypass_source_(bypass_source) {}
386
387 private:
390 Status DoEnable() override {
391 // If `config_` is specified, the PLL should be enabled and the phase
392 // fractional divider PFD0 needs to get configured, otherwise the PLL
393 // operates in bypass mode.
394 if (config_ != nullptr) {
395 // Configure Sys PLL clock source.
396 CLOCK_InitSysPll(config_);
397
398 if (sys_pfd0_divider_ != 0) {
399 CLOCK_InitSysPfd(kCLOCK_Pfd0, sys_pfd0_divider_);
400 }
401 if (sys_pfd1_divider_ != 0) {
402 CLOCK_InitSysPfd(kCLOCK_Pfd1, sys_pfd1_divider_);
403 }
404 if (sys_pfd2_divider_ != 0) {
405 CLOCK_InitSysPfd(kCLOCK_Pfd2, sys_pfd2_divider_);
406 }
407 if (sys_pfd3_divider_ != 0) {
408 CLOCK_InitSysPfd(kCLOCK_Pfd3, sys_pfd3_divider_);
409 }
410 } else {
411 // PLL operates in bypass mode.
412 CLKCTL0->SYSPLL0CLKSEL = bypass_source_;
413 CLKCTL0->SYSPLL0CTL0 |= CLKCTL0_SYSPLL0CTL0_BYPASS_MASK;
414 }
415 return OkStatus();
416 }
417
419 Status DoDisable() override {
420 if (config_ != nullptr) {
421 // Clock gate all the phase fractional divider PFD.
422 CLOCK_DeinitSysPfd(kCLOCK_Pfd0);
423 CLOCK_DeinitSysPfd(kCLOCK_Pfd1);
424 CLOCK_DeinitSysPfd(kCLOCK_Pfd2);
425 CLOCK_DeinitSysPfd(kCLOCK_Pfd3);
426 }
427
428 // Power down Sys PLL
429 CLOCK_DeinitSysPll();
430 return OkStatus();
431 }
432
434 const clock_sys_pll_config_t* config_ = nullptr;
435
437 const uint8_t sys_pfd0_divider_ = 0;
438 const uint8_t sys_pfd1_divider_ = 0;
439 const uint8_t sys_pfd2_divider_ = 0;
440 const uint8_t sys_pfd3_divider_ = 0;
441
443 const sys_pll_src_t bypass_source_ = kCLOCK_SysPllNone;
444};
445
449
454
457
462
467template <typename ElementType>
468class ClockMcuxpressoRtc final : public DependentElement<ElementType> {
469 public:
472 constexpr ClockMcuxpressoRtc(ElementType& source)
473 : DependentElement<ElementType>(source) {}
474
475 private:
477 Status DoEnable() final {
478 // Enable 32kHZ output of RTC oscillator.
479 CLOCK_EnableOsc32K(true);
480 return OkStatus();
481 }
482
485 // Disable 32KHz output of RTC oscillator.
486 CLOCK_EnableOsc32K(false);
487 return OkStatus();
488 }
489};
490
495
500
507template <typename ElementType>
508class ClockMcuxpressoClockIp final : public DependentElement<ElementType> {
509 public:
512 constexpr ClockMcuxpressoClockIp(ElementType& source, clock_ip_name_t clock)
513 : DependentElement<ElementType>(source), clock_(clock) {}
514
515 private:
517 Status DoEnable() final {
518 CLOCK_EnableClock(clock_);
519 return OkStatus();
520 }
521
524 CLOCK_DisableClock(clock_);
525 return OkStatus();
526 }
527
528 clock_ip_name_t clock_;
529};
530
535
540} // namespace pw::clock_tree
Definition: status.h:86
Definition: clock_tree.h:414
Definition: clock_tree.h:298
Definition: clock_tree.h:120
Definition: clock_tree.h:508
Definition: clock_tree.h:257
Definition: clock_tree.h:169
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:468
Definition: clock_tree.h:212
Definition: clock_tree.h:366
Definition: clock_tree.h:238
Definition: clock_tree.h:299
constexpr ClockMcuxpressoAudioPll(ElementType &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:301
Status DoDisable() final
Disable low power oscillator.
Definition: clock_tree.h:65
Status DoDisable() final
Disable 32 kHz RTS oscillator.
Definition: clock_tree.h:484
constexpr ClockMcuxpressoDivider(ElementType &source, clock_div_name_t divider_name, uint32_t divider)
Definition: clock_tree.h:261
Status DoEnable() final
Enable low power oscillator.
Definition: clock_tree.h:54
Status DoEnable() final
Enable selector.
Definition: clock_tree.h:226
Status DoEnable() final
Enable the clock.
Definition: clock_tree.h:517
Status DoDisable() final
Disable the clock.
Definition: clock_tree.h:523
Status DoEnable() final
Set the divider configuration.
Definition: clock_tree.h:269
constexpr ClockMcuxpressoSelector(ElementType &source, clock_attach_id_t selector_enable, clock_attach_id_t selector_disable)
Definition: clock_tree.h:217
Status DoEnable() final
Set MCLK IN clock frequency.
Definition: clock_tree.h:87
constexpr ClockMcuxpressoClockIp(ElementType &source, clock_ip_name_t clock)
Definition: clock_tree.h:512
Status DoDisable() override
Disables the Sys PLL logic.
Definition: clock_tree.h:419
constexpr ClockMcuxpressoMclk(ElementType &source, uint32_t frequency)
Definition: clock_tree.h:82
Status DoEnable() override
Definition: clock_tree.h:316
constexpr ClockMcuxpressoFrg(ElementType &source, const clock_frg_clk_config_t &config)
Constructor specifying the source clock and FRG configuration.
Definition: clock_tree.h:172
constexpr ClockMcuxpressoSysPll(ElementType &source, sys_pll_src_t bypass_source)
Constructor to place the Sys PLL into bypass mode.
Definition: clock_tree.h:383
Status DoDisable() final
Disable selector.
Definition: clock_tree.h:232
constexpr ClockMcuxpressoFro(clock_fro_output_en_t fro_output)
Constructor specifying the FRO divider output to manage.
Definition: clock_tree.h:29
constexpr ClockMcuxpressoAudioPll(ElementType &source, audio_pll_src_t bypass_source)
Constructor to place the Audio PLL into bypass mode.
Definition: clock_tree.h:309
Status DoEnable() override
Definition: clock_tree.h:390
Status DoEnable() final
Enable 32 kHz RTC oscillator.
Definition: clock_tree.h:477
Status DoEnable() final
Set CLK IN clock frequency.
Definition: clock_tree.h:129
constexpr ClockMcuxpressoClkIn(ElementType &source, uint32_t frequency)
Definition: clock_tree.h:124
Status DoDisable() final
Disable this FRO divider.
Definition: clock_tree.h:40
Status DoDisable() final
Disable FRG configuration.
Definition: clock_tree.h:188
Status DoDisable() override
Disables the audio PLL logic.
Definition: clock_tree.h:333
Status DoEnable() final
Enable FRG configuration.
Definition: clock_tree.h:182
constexpr ClockMcuxpressoRtc(ElementType &source)
Definition: clock_tree.h:472
Status DoDisable() final
Set MCLK IN clock frequency to 0 Hz.
Definition: clock_tree.h:94
Status DoDisable() final
Set CLK IN clock frequency to 0 Hz.
Definition: clock_tree.h:140
constexpr ClockMcuxpressoSysPll(ElementType &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:369
Status DoEnable() final
Enable this FRO divider.
Definition: clock_tree.h:34
uint32_t divider() const
Get current divider value.
Definition: clock_tree.h:446
Clock tree management library.
Definition: clock_tree.h:30
constexpr Status OkStatus()
Definition: status.h:235