-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrec.rs
648 lines (627 loc) · 23.2 KB
/
rec.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
//! Peripheral Reset and Enable Control (REC)
//!
//! This module contains safe accessors to the RCC functionality for each
//! peripheral.
//!
//! At a minimum each peripheral implements
//! [ResetEnable](trait.ResetEnable.html). Peripherals that have an
//! individual clock multiplexer in the PKSU also have methods
//! `kernel_clk_mux` and `get_kernel_clk_mux`. These set and get the state
//! of the kernel clock multiplexer respectively.
//!
//! Peripherals that share a clock multiplexer in the PKSU with other
//! peripherals implement a trait with a `get_kernel_clk_mux` method that
//! returns the current kernel clock state. Because the kernel_clk_mux is shared
//! between multiple peripherals, it cannot be set by any individual one of
//! them. Instead it can only be set by methods on the
//! [`PeripheralRec`](struct.PeripheralREC.html) itself. These methods are named
//! `kernel_xxxx_clk_mux()`.
//!
//! # Reset/Enable Example
//!
//! ```
//! // Constrain and Freeze power
//! ...
//! let rcc = dp.RCC.constrain();
//! let ccdr = rcc.sys_ck(100.MHz()).freeze(pwrcfg, &dp.SYSCFG);
//!
//! // Enable the clock to a peripheral and reset it
//! ccdr.peripheral.FDCAN.enable().reset();
//! ```
//!
//! # Individual Kernel Clock Example
//! ```
//! let ccdr = ...; // Returned by `freeze()`, see example above
//!
//! // Set individual kernel clock
//! let cec_prec = ccdr.peripheral.CEC.kernel_clk_mux(CecClkSel::LSI);
//!
//! assert_eq!(cec_prec.get_kernel_clk_mux(), CecClkSel::LSI);
//! ```
//!
//! # Group Kernel Clock Example
//! ```
//! let mut ccdr = ...; // Returned by `freeze()`, see example above
//!
//! // Set group kernel clock mux
//! ccdr.peripheral.kernel_i2c123_clk_mux(I2c123ClkSel::PLL3_R);
//!
//! // Enable and reset peripheral
//! let i2c3_prec = ccdr.peripheral.I2C3.enable().reset();
//!
//! assert_eq!(i2c3_prec.get_kernel_clk_mux(), I2c123ClkSel::PLL3_R);
//!
//! // Some method that consumes the i2c3 prec
//! init_i2c3(..., i2c3_prec);
//!
//! // Can't set group kernel clock (it would also affect I2C3)
//! // ccdr.peripheral.kernel_i2c123_clk_mux(I2c123ClkSel::HSI_KER);
//! ```
//!
//! # REC object
//!
//! There is a REC object for each peripheral. For example:
//!
//! ```
//! let rec_object = ccdr.peripheral.FDCAN;
//! ```
//!
//! If REC object is dropped by user code, then the Reset or Enable state of
//! this peripheral cannot be modified for the lifetime of the program.
#![deny(missing_docs)]
use core::marker::PhantomData;
use super::Rcc;
use crate::stm32::{rcc, RCC};
use cortex_m::interrupt;
use paste;
/// A trait for Resetting, Enabling and Disabling a single peripheral
pub trait ResetEnable {
/// Enable this peripheral
#[allow(clippy::return_self_not_must_use)]
fn enable(self) -> Self;
/// Disable this peripheral
#[allow(clippy::return_self_not_must_use)]
fn disable(self) -> Self;
/// Reset this peripheral
#[allow(clippy::return_self_not_must_use)]
fn reset(self) -> Self;
}
/// The clock gating state of a peripheral in low-power mode
#[derive(Default, Copy, Clone, PartialEq, Eq)]
pub enum LowPowerMode {
/// Kernel and bus interface clocks are not provided in low-power modes.
Off,
/// Kernel and bus interface clocks are provided in CSleep mode.
#[default]
Enabled,
}
impl Rcc {
/// Returns all the peripherals resets / enables / kernel clocks.
///
/// # Use case
///
/// Allows peripherals to be reset / enabled before the calling
/// freeze. For example, the internal watchdog could be enabled to
/// issue a reset if the call to freeze hangs waiting for an external
/// clock that is stopped.
///
/// # Safety
///
/// If this method is called multiple times, or is called before the
/// [freeze](struct.Rcc.html#freeze), then multiple accesses to the
/// same memory exist.
#[inline]
pub unsafe fn steal_peripheral_rec(&self) -> PeripheralREC {
PeripheralREC::new_singleton()
}
}
// This macro uses the paste::item! macro to create identifiers.
//
// https://crates.io/crates/paste
macro_rules! peripheral_reset_and_enable_control {
($( #[ $tmeta:meta ] $AXBn:ident, $axb_doc:expr => [
$(
$( #[ $pmeta:meta ] )*
$(($NoReset:ident))? $p:ident
$([ kernel $clk:ident: $pk:ident $(($Variant:ident))* $pk_alias:ident $ccip:ident $clk_doc:expr ])*
$([ group clk: $pk_g:ident $( $(($Variant_g:ident))* $pk_g_alias:ident $ccip_g:ident $clk_doc_g:expr )* ])*
$([ fixed clk: $clk_doc_f:expr ])*
),*
];)+) => {
paste::item! {
/// Peripheral Reset and Enable Control
#[allow(non_snake_case)]
#[non_exhaustive]
pub struct PeripheralREC {
$(
$(
#[allow(missing_docs)]
#[ $tmeta ]
$( #[ $pmeta ] )*
pub [< $p:upper >]: $p,
)*
)+
}
impl PeripheralREC {
/// Return a new instance of the peripheral resets /
/// enables / kernel clocks
///
/// # Safety
///
/// If this method is called multiple times, then multiple
/// accesses to the same memory exist.
pub(super) unsafe fn new_singleton() -> PeripheralREC {
PeripheralREC {
$(
$(
#[ $tmeta ]
$( #[ $pmeta ] )*
[< $p:upper >]: $p {
_marker: PhantomData,
},
)*
)+
}
}
}
$(
$(
#[ $tmeta ]
peripheral_reset_and_enable_control_generator! (
$AXBn, $(($NoReset))* $p, [< $p:upper >], [< $p:lower >],
$( $pmeta )*
$(
[kernel $clk: $pk $(($Variant))* $pk_alias $ccip $clk_doc]
)*
$(
[group clk: $pk_g [< $pk_g:lower >] $( $(($Variant_g))* $pk_g_alias $ccip_g $clk_doc_g )* ]
)*
$(
[fixed clk: $clk_doc_f]
)*
);
)*
)+
}
}
}
macro_rules! peripheral_reset_function_behavior {
(
$AXBn:ident,
$p:ident
) => {
paste::item! {
// unsafe: Owned exclusive access to this bitfield
interrupt::free(|_| {
let rstr = unsafe {
&(*RCC::ptr()).[< $AXBn:lower rstr >]()
};
rstr.modify(|_, w| w.
[< $p:lower rst >]().set_bit());
rstr.modify(|_, w| w.
[< $p:lower rst >]().clear_bit());
});
}
};
(
$AXBn:ident,
$NoReset:ident $p:ident
) => {};
}
// This macro uses the paste::item! macro to create identifiers.
//
// https://crates.io/crates/paste
//
// The macro is intended only to be called from within the
// peripheral_reset_and_enable_control macro
macro_rules! peripheral_reset_and_enable_control_generator {
(
$AXBn:ident,
$(($NoReset:ident))? $p:ident,
$p_upper:ident, // Lower and upper case $p available for use in
$p_lower:ident, // comments, equivalent to with the paste macro.
$( $pmeta:meta )*
$([ kernel $clk:ident: $pk:ident $(($Variant:ident))* $pk_alias:ident $ccip:ident $clk_doc:expr ])*
$([ group clk: $pk_g:ident $pk_g_lower:ident $( $(($Variant_g:ident))* $pk_g_alias:ident $ccip_g:ident $clk_doc_g:expr )* ])*
$([ fixed clk: $clk_doc_f:expr ])*
) => {
paste::item! {
#[doc = " Reset, Enable and Clock functionality for " $p]
///
/// # Reset/Enable Example
///
/// ```
/// let ccdr = ...; // From RCC
///
/// // Enable the clock to the peripheral and reset it
#[doc = "ccdr.peripheral." $p_upper ".enable().reset();"]
/// ```
///
$( // Individual kernel clocks
/// # Individual Kernel Clock
///
/// This peripheral has its own dedicated kernel clock.
#[doc = "See [" $pk "ClkSel](crate::rcc::rec::" $pk "ClkSel) "
"for possible clock sources."]
///
/// ```
/// let ccdr = ...; // From RCC
///
/// // Set individual kernel clock
#[doc = "let " $p_lower "_prec = ccdr.peripheral." $p_upper
".kernel_clk_mux(" $pk "ClkSel::XX_clock_soruce_XX);"]
///
#[doc = "assert_eq!(" $p_lower "_prec.get_kernel_clk_mux(), "
$pk "ClkSel::XX_clock_source_XX);"]
/// ```
)*
$( // Group kernel clocks
/// # Group Kernel Clock
///
/// This peripheral has a kernel clock that is shared with other
/// peripherals.
///
#[doc = "Since it is shared, it must be set using the "
"[kernel_" $pk_g_lower "_clk_mux](crate::rcc::rec::PeripheralREC#method"
".kernel_" $pk_g_lower "_clk_mux) method."]
///
/// ```
/// let mut ccdr = ...; // From RCC
///
/// // Set group kernel clock mux
#[doc = " ccdr.peripheral."
"kernel_" $pk_g_lower "_clk_mux("
$pk_g "ClkSel::XX_clock_source_XX);"]
///
#[doc = " assert_eq!(ccdr.peripheral." $p_upper
".get_kernel_clk_mux(), " $pk_g "ClkSel::XX_clock_source_XX);"]
)*
$( // Fixed kernel clocks
/// # Fixed Kernel Clock
///
/// This peripheral has a kernel clock that is always equal to
#[doc= $clk_doc_f "."]
)*
$( #[ $pmeta ] )*
pub struct $p {
pub(crate) _marker: PhantomData<*const ()>,
}
$( #[ $pmeta ] )*
impl $p {
/// Set Low Power Mode for peripheral
#[allow(clippy::return_self_not_must_use)]
pub fn low_power(self, lpm: LowPowerMode) -> Self {
// unsafe: Owned exclusive access to this bitfield
interrupt::free(|_| {
// LPEN
let lpenr = unsafe {
&(*RCC::ptr()).[< $AXBn:lower lpenr >]()
};
lpenr.modify(|_, w| w.[< $p:lower lpen >]()
.bit(lpm != LowPowerMode::Off));
});
self
}
}
$( #[ $pmeta ] )*
unsafe impl Send for $p {}
$( #[ $pmeta ] )*
impl ResetEnable for $p {
#[inline(always)]
fn enable(self) -> Self {
// unsafe: Owned exclusive access to this bitfield
interrupt::free(|_| {
let enr = unsafe {
&(*RCC::ptr()).[< $AXBn:lower enr >]()
};
enr.modify(|_, w| w.
[< $p:lower en >]().set_bit());
});
self
}
#[inline(always)]
fn disable(self) -> Self {
// unsafe: Owned exclusive access to this bitfield
interrupt::free(|_| {
let enr = unsafe {
&(*RCC::ptr()).[< $AXBn:lower enr >]()
};
enr.modify(|_, w| w.
[< $p:lower en >]().clear_bit());
});
self
}
#[inline(always)]
fn reset(self) -> Self {
peripheral_reset_function_behavior!($AXBn, $($NoReset)? $p);
self
}
}
$( #[ $pmeta ] )*
impl $p {
$( // Individual kernel clocks
#[inline(always)]
#[allow(clippy::return_self_not_must_use)]
/// Modify the kernel clock for
#[doc=$clk_doc "."]
/// See RM0433 Rev 7 Section 8.5.8.
///
/// It is possible to switch this clock dynamically without
/// generating spurs or timing violations. However, the user
/// must ensure that both clocks are running. See RM0433 Rev
/// 7 Section 8.5.10.
pub fn [< kernel_ $clk _mux >](self, sel: [< $pk ClkSel >]) -> Self {
// unsafe: Owned exclusive access to this bitfield
interrupt::free(|_| {
let ccip = unsafe {
&(*RCC::ptr()).[< $ccip >]()
};
ccip.modify(|_, w| w.
[< $pk:lower sel >]().variant(sel));
});
self
}
#[inline(always)]
/// Return the current kernel clock selection
pub fn [< get_kernel_ $clk _mux>](&self) ->
variant_return_type!([< $pk ClkSel >] $(, $Variant)*)
{
// unsafe: We only read from this bitfield
let ccip = unsafe {
&(*RCC::ptr()).[< $ccip >]()
};
ccip.read().[< $pk:lower sel >]().variant()
}
)*
}
$( // Individual kernel clocks
#[doc=$clk_doc]
/// kernel clock source selection
pub type [< $pk ClkSel >] =
rcc::[< $ccip >]::[< $pk_alias SEL >];
)*
$( // Group kernel clocks
impl [< $pk_g ClkSelGetter >] for $p {}
)*
$( // Group kernel clocks
$(
#[doc=$clk_doc_g]
/// kernel clock source selection.
pub type [< $pk_g ClkSel >] =
rcc::[< $ccip_g >]::[< $pk_g_alias SEL >];
/// Can return
#[doc=$clk_doc_g]
/// kernel clock source selection
pub trait [< $pk_g ClkSelGetter >] {
#[inline(always)]
#[allow(unused)]
/// Return the
#[doc=$clk_doc_g]
/// kernel clock selection
fn get_kernel_clk_mux(&self) ->
variant_return_type!([< $pk_g ClkSel >] $(, $Variant_g)*)
{
// unsafe: We only read from this bitfield
let ccip = unsafe {
&(*RCC::ptr()).[< $ccip_g >]()
};
ccip.read().[< $pk_g:lower sel >]().variant()
}
}
)*
)*
impl PeripheralREC {
$( // Group kernel clocks
$(
/// Modify the kernel clock for
#[doc=$clk_doc_g "."]
/// See RM0492 Revision 2 Section 10.4.12.
///
/// It is possible to switch this clock dynamically
/// without generating spurs or timing
/// violations. However, the user must ensure that both
/// clocks are running. See RM0433 Rev 7 Section 8.5.10.
pub fn [< kernel_ $pk_g:lower _clk_mux >](&mut self, sel: [< $pk_g ClkSel >]) -> &mut Self {
// unsafe: Owned exclusive access to this bitfield
interrupt::free(|_| {
let ccip = unsafe {
&(*RCC::ptr()).[< $ccip_g >]()
};
ccip.modify(|_, w| w.
[< $pk_g:lower sel >]().variant(sel));
});
self
}
)*
)*
}
}
}
}
// If the PAC does not fully specify a CCIP field (perhaps because one or
// more values are reserved), then we use a different return type
macro_rules! variant_return_type {
($t:ty) => { $t };
($t:ty, $Variant: ident) => {
Option<$t>
};
}
// Enumerate all peripherals and optional clock multiplexers
//
// Peripherals are grouped by bus for convenience. Each bus is specified like:
// #[attribute] name, "description" => [..];
//
// The attribute is mandatory for the bus grouping, but can just be
// #[cfg(all())]. The description is not used. Each bus grouping can be repeated
// multiple times if needed.
//
// As well as busses, peripherals can optionally be preceeded by a conditional
// compilation attribute. However, this only works for peripherals without
// kernel clock multiplexers.
//
// Peripherals with an individual kernel clock must be marked "kernel clk". If a
// kernel clock multiplexer is shared between multiple peripherals, all those
// peripherals must instead be marked with a common "group clk".
peripheral_reset_and_enable_control! {
#[cfg(all())]
AHB1, "AMBA High-performance Bus (AHB1) peripherals" => [
(NoReset) Sram1,
(NoReset) BkpRam,
RamCfg,
Crc,
(NoReset) Flitf,
Gpdma1,
Gpdma2
];
#[cfg(feature = "rm0492")]
AHB1, "" => [
(NoReset) Gtzc1
];
#[cfg(feature = "rm0481")]
AHB1, "" => [
(NoReset) Dcache,
(NoReset) Tzsc1,
Fmac,
Cordic
];
#[cfg(feature = "ethernet")]
AHB1, "" => [
(NoReset) Ethrx,
(NoReset) Ethtx,
Eth
];
#[cfg(all())]
AHB2, "AMBA High-performance Bus (AHB2) peripherals" => [
(NoReset) Sram2,
Hash,
Gpioh,
Gpiod,
Gpioc,
Gpiob,
Gpioa,
Rng [kernel clk: Rng RNG ccipr5 "RNG"],
Adc [group clk: AdcDac(Variant) ADCDAC ccipr5 "ADC/DAC"]
];
#[cfg(feature = "rm0492")]
AHB2, "" => [
Dac12 [group clk: AdcDac]
];
#[cfg(feature = "rm0481")]
AHB2, "" => [
Gpiog,
Gpiof,
Gpioe,
Dac1 [group clk: AdcDac]
];
#[cfg(feature = "h56x_h573")]
AHB2, "" => [
Gpioi
];
#[cfg(feature = "rm0481")]
AHB4, "AMBA High-performance Bus (AHB4) peripherals" => [
Octospi1 [kernel clk: Octospi1 OCTOSPI1 ccipr4 "OCTOSPI1"],
Fmc,
Sdmmc1 [kernel clk: Sdmmc1 SDMMC ccipr4 "SDMMC1"]
];
#[cfg(feature = "sdmmc2")]
AHB4, "" => [
Sdmmc2 [kernel clk: Sdmmc2 SDMMC ccipr4 "SDMMC2"]
];
#[cfg(feature = "otfdec")]
AHB4, "" => [
Otfdec1
];
#[cfg(all())]
APB1L, "Advanced Peripheral Bus 1L (APB1L) peripherals" => [
Usart2 [kernel clk: Usart2(Variant) USART ccipr1 "USART2"],
Usart3 [kernel clk: Usart3(Variant) USART ccipr1 "USART3"],
Crs,
I3c1 [kernel clk: I3c1(Variant) I3C ccipr4 "I3C1"],
I2c2 [kernel clk: I2c2 I2C ccipr4 "I2C2"],
I2c1 [kernel clk: I2c1 I2C ccipr4 "I2C1"],
Spi3 [kernel clk: Spi3(Variant) SPI123 ccipr3 "SPI3"],
Spi2 [kernel clk: Spi2(Variant) SPI123 ccipr3 "SPI2"],
(NoReset) Wwdg,
Tim2, Tim3, Tim6, Tim7
];
#[cfg(feature = "rm0492")]
APB1L, "" => [
Opamp,
Comp
];
#[cfg(feature = "rm0481")]
APB1L, "" => [
Cec [kernel clk: Cec(Variant) CEC ccipr5 "CEC"],
Usart6 [kernel clk: Usart6(Variant) USART ccipr1 "USART6"],
Uart5 [kernel clk: Uart5(Variant) USART ccipr1 "USART5"],
Uart4 [kernel clk: Uart4(Variant) USART ccipr1 "USART4"],
Tim12, Tim5, Tim4
];
#[cfg(feature = "h56x_h573")]
APB1L, "" => [
Uart8 [kernel clk: Uart8(Variant) USART ccipr1 "UART8"],
Uart7 [kernel clk: Uart7(Variant) USART ccipr1 "UART7"],
Usart11 [kernel clk: Usart11(Variant) USART ccipr2 "USART11"],
Usart10 [kernel clk: Usart10(Variant) USART ccipr1 "USART10"],
Tim14, Tim13
];
#[cfg(all())]
APB1H, "Advanced Peripheral Bus 1H (APB1H) peripherals" => [
Fdcan [kernel clk: Fdcan(Variant) FDCAN ccipr5 "FDCAN"],
Lptim2 [kernel clk: Lptim2(Variant) LPTIM ccipr2 "LPTIM2"],
Dts
];
#[cfg(feature = "rm0481")]
APB1H, "" => [
Ucpd1
];
#[cfg(feature = "h56x_h573")]
APB1H, "" => [
Uart12 [kernel clk: Uart12(Variant) USART ccipr2 "USART12"],
Uart9 [kernel clk: Uart9(Variant) USART ccipr1 "UART9"]
];
#[cfg(all())]
APB2, "Advanced Peripheral Bus 2 (APB2) peripherals" => [
Usb [kernel clk: Usb USB ccipr4 "USB"],
Usart1 [kernel clk: Usart1(Variant) USART ccipr1 "USART1"],
Spi1 [kernel clk: Spi1(Variant) SPI123 ccipr3 "SPI1"],
Tim1
];
#[cfg(feature = "rm0481")]
APB2, "" => [
Sai2 [kernel clk: Sai2(Variant) SAI ccipr5 "SAI2"],
Sai1 [kernel clk: Sai1(Variant) SAI ccipr5 "SAI1"],
Spi4 [kernel clk: Spi4(Variant) SPI456 ccipr3 "SPI4"],
Tim15, Tim8
];
#[cfg(feature = "h56x_h573")]
APB2, "" => [
Spi6 [kernel clk: Spi6(Variant) SPI456 ccipr3 "SPI6"],
Tim17, Tim16
];
#[cfg(all())]
APB3, "Advanced Peripheral Bus 3 (APB3) peripherals" => [
(NoReset) RtcApb,
LpTim1 [kernel clk: LpTim1(Variant) LPTIM ccipr2 "LPTIM1"],
LpUart1 [kernel clk: LpUart1(Variant) USART ccipr3 "LPUART1"],
(NoReset) Sbs
];
#[cfg(feature = "rm0481")]
APB3, "" => [
Vref,
I2c3 [kernel clk: I2c3 I2C ccipr4 "I2C3"]
];
#[cfg(feature = "h56x_h573")]
APB3, "" => [
LpTim6 [kernel clk: LpTim6(Variant) LPTIM ccipr2 "LPTIM6"],
LpTim5 [kernel clk: LpTim5(Variant) LPTIM ccipr2 "LPTIM5"],
LpTim4 [kernel clk: LpTim4(Variant) LPTIM ccipr2 "LPTIM4"],
LpTim3 [kernel clk: LpTim3(Variant) LPTIM ccipr2 "LPTIM3"],
I2c4 [kernel clk: I2c4 I2C ccipr4 "I2C4"],
Spi5 [kernel clk: Spi5(Variant) SPI456 ccipr3 "SPI5"]
];
#[cfg(any(feature = "rm0492", feature = "h523_h533"))]
APB3, "" => [
I3c2 [kernel clk: I3c2(Variant) I3C ccipr4 "I3C2"]
];
}