Pigweed
 
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
24 : public ClockSource<ElementNonBlockingCannotFail> {
25 public:
27 constexpr ClockMcuxpressoFro(clock_fro_output_en_t fro_output)
28 : fro_output_(fro_output) {}
29
30 private:
32 Status DoEnable() final {
33 CLOCK_EnableFroClk(CLKCTL0->FRODIVOEN | fro_output_);
34 return OkStatus();
35 }
36
38 Status DoDisable() final {
39 CLOCK_EnableFroClk(CLKCTL0->FRODIVOEN & ~fro_output_);
40 return OkStatus();
41 }
42
44 const uint32_t fro_output_;
45};
46
49 : public ClockSource<ElementNonBlockingCannotFail> {
50 private:
52 Status DoEnable() final {
53 // Power up the 1MHz low power oscillator power domain.
54 POWER_DisablePD(kPDRUNCFG_PD_LPOSC);
55 // POWER_ApplyPD() is not necessary for LPOSC_PD.
56
57 // Wait for the low power oscillator to stabilize.
58 CLOCK_EnableLpOscClk();
59 return OkStatus();
60 }
61
63 Status DoDisable() final {
64 // Power down the 1MHz low power oscillator power domain.
65 POWER_EnablePD(kPDRUNCFG_PD_LPOSC);
66 // POWER_ApplyPD() is not necessary for LPOSC_PD.
67 return OkStatus();
68 }
69};
70
75template <typename ElementType>
76class ClockMcuxpressoMclk final : public DependentElement<ElementType> {
77 public:
80 constexpr ClockMcuxpressoMclk(ElementType& source, uint32_t frequency)
81 : DependentElement<ElementType>(source), frequency_(frequency) {}
82
83 private:
85 Status DoEnable() final {
86 // Set global that stores external MCLK IN clock frequency.
87 CLOCK_SetMclkFreq(frequency_);
88 return OkStatus();
89 }
90
92 Status DoDisable() final {
93 // Set global that stores external MCLK IN clock frequency to zero.
94 CLOCK_SetMclkFreq(0);
95 return OkStatus();
96 }
97
99 uint32_t frequency_;
100};
101
105using ClockMcuxpressoMclkBlocking = ClockMcuxpressoMclk<ElementBlocking>;
106
109using ClockMcuxpressoMclkNonBlocking =
110 ClockMcuxpressoMclk<ElementNonBlockingCannotFail>;
111
117template <typename ElementType>
118class ClockMcuxpressoClkIn final : public DependentElement<ElementType> {
119 public:
122 constexpr ClockMcuxpressoClkIn(ElementType& source, uint32_t frequency)
123 : DependentElement<ElementType>(source), frequency_(frequency) {}
124
125 private:
127 Status DoEnable() final {
128 // Set global that stores external CLK IN pin clock frequency.
129 CLOCK_SetClkinFreq(frequency_);
130
131 // OSC clock source selector ClkIn.
132 const uint8_t kCLOCK_OscClkIn = CLKCTL0_SYSOSCBYPASS_SEL(1);
133 CLKCTL0->SYSOSCBYPASS = kCLOCK_OscClkIn;
134 return OkStatus();
135 }
136
139 // Set global that stores external CLK IN pin clock frequency to zero.
140 CLOCK_SetClkinFreq(0);
141
142 // Set OSC clock source selector None, which gates output to reduce power.
143 const uint8_t kCLOCK_OscNone = CLKCTL0_SYSOSCBYPASS_SEL(7);
144 CLKCTL0->SYSOSCBYPASS = kCLOCK_OscNone;
145 return OkStatus();
146 }
147
149 uint32_t frequency_;
150};
151
155using ClockMcuxpressoClkInBlocking = ClockMcuxpressoClkIn<ElementBlocking>;
156
159using ClockMcuxpressoClkInNonBlocking =
160 ClockMcuxpressoClkIn<ElementNonBlockingCannotFail>;
161
166template <typename ElementType>
167class ClockMcuxpressoFrg final : public DependentElement<ElementType> {
168 public:
170 constexpr ClockMcuxpressoFrg(ElementType& source,
171 const clock_frg_clk_config_t& config)
172 : DependentElement<ElementType>(source), config_(config) {}
173
174 private:
175 // FRG clock source selector None, which gates output to reduce power.
176 // The None source selector is not defined in the SDK.
177 const uint8_t kCLOCK_FrgNone = 7;
178
180 Status DoEnable() final {
181 CLOCK_SetFRGClock(&config_);
182 return OkStatus();
183 }
184
187 clock_frg_clk_config_t disable_config = config_;
188 static_assert(sizeof(disable_config.sfg_clock_src) ==
189 sizeof(kCLOCK_FrgNone));
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
201using ClockMcuxpressoFrgBlocking = ClockMcuxpressoFrg<ElementBlocking>;
202
204using ClockMcuxpressoFrgNonBlocking =
205 ClockMcuxpressoFrg<ElementNonBlockingCannotFail>;
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
244using ClockMcuxpressoSelectorBlocking =
245 ClockMcuxpressoSelector<ElementBlocking>;
246
249using ClockMcuxpressoSelectorNonBlocking =
250 ClockMcuxpressoSelector<ElementNonBlockingCannotFail>;
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
279using ClockMcuxpressoDividerBlocking = ClockMcuxpressoDivider<ElementBlocking>;
280
283using ClockMcuxpressoDividerNonBlocking =
284 ClockMcuxpressoDivider<ElementNonBlockingCannotFail>;
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
355using ClockMcuxpressoAudioPllBlocking =
356 ClockMcuxpressoAudioPll<ElementBlocking>;
357
360using ClockMcuxpressoAudioPllNonBlocking =
361 ClockMcuxpressoAudioPll<ElementNonBlockingCannotFail>;
362
367template <typename ElementType>
368class ClockMcuxpressoRtc final : public DependentElement<ElementType> {
369 public:
372 constexpr ClockMcuxpressoRtc(ElementType& source)
373 : DependentElement<ElementType>(source) {}
374
375 private:
377 Status DoEnable() final {
378 // Enable 32kHZ output of RTC oscillator.
379 CLOCK_EnableOsc32K(true);
380 return OkStatus();
381 }
382
385 // Disable 32KHz output of RTC oscillator.
386 CLOCK_EnableOsc32K(false);
387 return OkStatus();
388 }
389};
390
394using ClockMcuxpressoRtcBlocking = ClockMcuxpressoRtc<ElementBlocking>;
395
398using ClockMcuxpressoRtcNonBlocking =
399 ClockMcuxpressoRtc<ElementNonBlockingCannotFail>;
400
407template <typename ElementType>
408class ClockMcuxpressoClockIp final : public DependentElement<ElementType> {
409 public:
412 constexpr ClockMcuxpressoClockIp(ElementType& source, clock_ip_name_t clock)
413 : DependentElement<ElementType>(source), clock_(clock) {}
414
415 private:
417 Status DoEnable() final {
418 CLOCK_EnableClock(clock_);
419 return OkStatus();
420 }
421
424 CLOCK_DisableClock(clock_);
425 return OkStatus();
426 }
427
428 clock_ip_name_t clock_;
429};
430
434using ClockMcuxpressoClockIpBlocking = ClockMcuxpressoClockIp<ElementBlocking>;
435
438using ClockMcuxpressoClockIpNonBlocking =
439 ClockMcuxpressoClockIp<ElementNonBlockingCannotFail>;
440} // namespace pw::clock_tree
Definition: status.h:85
Definition: clock_tree.h:365
uint32_t divider() const
Get current divider value.
Definition: clock_tree.h:396
Definition: clock_tree.h:298
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 DoEnable() override
Definition: clock_tree.h:316
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 DoDisable() override
Disables the audio PLL logic.
Definition: clock_tree.h:333
Definition: clock_tree.h:118
Status DoEnable() final
Set CLK IN clock frequency.
Definition: clock_tree.h:127
constexpr ClockMcuxpressoClkIn(ElementType &source, uint32_t frequency)
Definition: clock_tree.h:122
Status DoDisable() final
Set CLK IN clock frequency to 0 Hz.
Definition: clock_tree.h:138
Definition: clock_tree.h:408
Status DoEnable() final
Enable the clock.
Definition: clock_tree.h:417
Status DoDisable() final
Disable the clock.
Definition: clock_tree.h:423
constexpr ClockMcuxpressoClockIp(ElementType &source, clock_ip_name_t clock)
Definition: clock_tree.h:412
Definition: clock_tree.h:257
constexpr ClockMcuxpressoDivider(ElementType &source, clock_div_name_t divider_name, uint32_t divider)
Definition: clock_tree.h:261
Status DoEnable() final
Set the divider configuration.
Definition: clock_tree.h:269
Definition: clock_tree.h:167
constexpr ClockMcuxpressoFrg(ElementType &source, const clock_frg_clk_config_t &config)
Constructor specifying the source clock and FRG configuration.
Definition: clock_tree.h:170
Status DoDisable() final
Disable FRG configuration.
Definition: clock_tree.h:186
Status DoEnable() final
Enable FRG configuration.
Definition: clock_tree.h:180
Class implementing an FRO clock source.
Definition: clock_tree.h:24
constexpr ClockMcuxpressoFro(clock_fro_output_en_t fro_output)
Constructor specifying the FRO divider output to manage.
Definition: clock_tree.h:27
Status DoDisable() final
Disable this FRO divider.
Definition: clock_tree.h:38
Status DoEnable() final
Enable this FRO divider.
Definition: clock_tree.h:32
Class implementing the low power oscillator clock source.
Definition: clock_tree.h:49
Status DoDisable() final
Disable low power oscillator.
Definition: clock_tree.h:63
Status DoEnable() final
Enable low power oscillator.
Definition: clock_tree.h:52
Definition: clock_tree.h:76
Status DoEnable() final
Set MCLK IN clock frequency.
Definition: clock_tree.h:85
constexpr ClockMcuxpressoMclk(ElementType &source, uint32_t frequency)
Definition: clock_tree.h:80
Status DoDisable() final
Set MCLK IN clock frequency to 0 Hz.
Definition: clock_tree.h:92
Definition: clock_tree.h:368
Status DoDisable() final
Disable 32 kHz RTS oscillator.
Definition: clock_tree.h:384
Status DoEnable() final
Enable 32 kHz RTC oscillator.
Definition: clock_tree.h:377
constexpr ClockMcuxpressoRtc(ElementType &source)
Definition: clock_tree.h:372
Definition: clock_tree.h:212
Status DoEnable() final
Enable selector.
Definition: clock_tree.h:226
constexpr ClockMcuxpressoSelector(ElementType &source, clock_attach_id_t selector_enable, clock_attach_id_t selector_disable)
Definition: clock_tree.h:217
Status DoDisable() final
Disable selector.
Definition: clock_tree.h:232
Definition: clock_tree.h:147
Definition: clock_tree.h:208
constexpr Status OkStatus()
Definition: status.h:234