2 * STM32L4X5 RCC (Reset and clock control)
4 * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
5 * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
7 * SPDX-License-Identifier: GPL-2.0-or-later
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
12 * The reference used is the STMicroElectronics RM0351 Reference manual
13 * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
15 * Inspired by the BCM2835 CPRMAN clock manager implementation by Luc Michel.
18 #include "qemu/osdep.h"
20 #include "qemu/module.h"
21 #include "qemu/timer.h"
22 #include "qapi/error.h"
23 #include "migration/vmstate.h"
24 #include "hw/misc/stm32l4x5_rcc.h"
25 #include "hw/misc/stm32l4x5_rcc_internals.h"
28 #include "hw/qdev-clock.h"
29 #include "hw/qdev-properties.h"
30 #include "hw/qdev-properties-system.h"
31 #include "hw/registerfields.h"
34 #define HSE_DEFAULT_FRQ 48000000ULL
35 #define HSI_FRQ 16000000ULL
36 #define MSI_DEFAULT_FRQ 4000000ULL
37 #define LSE_FRQ 32768ULL
38 #define LSI_FRQ 32000ULL
41 * Function to simply acknowledge and propagate changes in a clock mux
43 * `bypass_source` allows to bypass the period of the current source and just
44 * consider it equal to 0. This is useful during the hold phase of reset.
46 static void clock_mux_update(RccClockMuxState
*mux
, bool bypass_source
)
49 Clock
*current_source
= mux
->srcs
[mux
->src
];
50 uint32_t freq_multiplier
= 0;
52 * To avoid rounding errors, we use the clock period instead of the
54 * This means that the multiplier of the mux becomes the divider of
55 * the clock and the divider of the mux becomes the multiplier of the
58 if (!bypass_source
&& mux
->enabled
&& mux
->divider
) {
59 freq_multiplier
= mux
->divider
;
62 clock_set_mul_div(mux
->out
, freq_multiplier
, mux
->multiplier
);
63 clock_update(mux
->out
, clock_get(current_source
));
65 src_freq
= clock_get_hz(current_source
);
66 /* TODO: can we simply detect if the config changed so that we reduce log spam ? */
67 trace_stm32l4x5_rcc_mux_update(mux
->id
, mux
->src
, src_freq
,
68 mux
->multiplier
, mux
->divider
);
71 static void clock_mux_src_update(void *opaque
, ClockEvent event
)
73 RccClockMuxState
**backref
= opaque
;
74 RccClockMuxState
*s
= *backref
;
76 * The backref value is equal to:
77 * s->backref + (sizeof(RccClockMuxState *) * update_src).
78 * By subtracting we can get back the index of the updated clock.
80 const uint32_t update_src
= backref
- s
->backref
;
81 /* Only update if the clock that was updated is the current source */
82 if (update_src
== s
->src
) {
83 clock_mux_update(s
, false);
87 static void clock_mux_init(Object
*obj
)
89 RccClockMuxState
*s
= RCC_CLOCK_MUX(obj
);
92 for (i
= 0; i
< RCC_NUM_CLOCK_MUX_SRC
; i
++) {
93 char *name
= g_strdup_printf("srcs[%zu]", i
);
95 s
->srcs
[i
] = qdev_init_clock_in(DEVICE(s
), name
,
102 s
->out
= qdev_init_clock_out(DEVICE(s
), "out");
105 static void clock_mux_reset_enter(Object
*obj
, ResetType type
)
107 RccClockMuxState
*s
= RCC_CLOCK_MUX(obj
);
108 set_clock_mux_init_info(s
, s
->id
);
111 static void clock_mux_reset_hold(Object
*obj
)
113 RccClockMuxState
*s
= RCC_CLOCK_MUX(obj
);
114 clock_mux_update(s
, true);
117 static void clock_mux_reset_exit(Object
*obj
)
119 RccClockMuxState
*s
= RCC_CLOCK_MUX(obj
);
120 clock_mux_update(s
, false);
123 static const VMStateDescription clock_mux_vmstate
= {
124 .name
= TYPE_RCC_CLOCK_MUX
,
126 .minimum_version_id
= 1,
127 .fields
= (VMStateField
[]) {
128 VMSTATE_UINT32(id
, RccClockMuxState
),
129 VMSTATE_ARRAY_CLOCK(srcs
, RccClockMuxState
,
130 RCC_NUM_CLOCK_MUX_SRC
),
131 VMSTATE_BOOL(enabled
, RccClockMuxState
),
132 VMSTATE_UINT32(src
, RccClockMuxState
),
133 VMSTATE_UINT32(multiplier
, RccClockMuxState
),
134 VMSTATE_UINT32(divider
, RccClockMuxState
),
135 VMSTATE_END_OF_LIST()
139 static void clock_mux_class_init(ObjectClass
*klass
, void *data
)
141 DeviceClass
*dc
= DEVICE_CLASS(klass
);
142 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
144 rc
->phases
.enter
= clock_mux_reset_enter
;
145 rc
->phases
.hold
= clock_mux_reset_hold
;
146 rc
->phases
.exit
= clock_mux_reset_exit
;
147 dc
->vmsd
= &clock_mux_vmstate
;
150 static void clock_mux_set_enable(RccClockMuxState
*mux
, bool enabled
)
152 if (mux
->enabled
== enabled
) {
157 trace_stm32l4x5_rcc_mux_enable(mux
->id
);
159 trace_stm32l4x5_rcc_mux_disable(mux
->id
);
162 mux
->enabled
= enabled
;
163 clock_mux_update(mux
, false);
166 static void clock_mux_set_factor(RccClockMuxState
*mux
,
167 uint32_t multiplier
, uint32_t divider
)
169 if (mux
->multiplier
== multiplier
&& mux
->divider
== divider
) {
172 trace_stm32l4x5_rcc_mux_set_factor(mux
->id
,
173 mux
->multiplier
, multiplier
, mux
->divider
, divider
);
175 mux
->multiplier
= multiplier
;
176 mux
->divider
= divider
;
177 clock_mux_update(mux
, false);
180 static void clock_mux_set_source(RccClockMuxState
*mux
, RccClockMuxSource src
)
182 if (mux
->src
== src
) {
186 trace_stm32l4x5_rcc_mux_set_src(mux
->id
, mux
->src
, src
);
188 clock_mux_update(mux
, false);
192 * Acknowledge and propagate changes in a PLL frequency.
193 * `bypass_source` allows to bypass the period of the current source and just
194 * consider it equal to 0. This is useful during the hold phase of reset.
196 static void pll_update(RccPllState
*pll
, bool bypass_source
)
198 uint64_t vco_freq
, old_channel_freq
, channel_freq
;
201 /* The common PLLM factor is handled by the PLL mux */
202 vco_freq
= muldiv64(clock_get_hz(pll
->in
), pll
->vco_multiplier
, 1);
204 for (i
= 0; i
< RCC_NUM_CHANNEL_PLL_OUT
; i
++) {
205 if (!pll
->channel_exists
[i
]) {
209 old_channel_freq
= clock_get_hz(pll
->channels
[i
]);
212 !pll
->channel_enabled
[i
] ||
213 !pll
->channel_divider
[i
]) {
216 channel_freq
= muldiv64(vco_freq
,
218 pll
->channel_divider
[i
]);
221 /* No change, early continue to avoid log spam and useless propagation */
222 if (old_channel_freq
== channel_freq
) {
226 clock_update_hz(pll
->channels
[i
], channel_freq
);
227 trace_stm32l4x5_rcc_pll_update(pll
->id
, i
, vco_freq
,
228 old_channel_freq
, channel_freq
);
232 static void pll_src_update(void *opaque
, ClockEvent event
)
234 RccPllState
*s
= opaque
;
235 pll_update(s
, false);
238 static void pll_init(Object
*obj
)
240 RccPllState
*s
= RCC_PLL(obj
);
243 s
->in
= qdev_init_clock_in(DEVICE(s
), "in",
244 pll_src_update
, s
, ClockUpdate
);
246 const char *names
[] = {
247 "out-p", "out-q", "out-r",
250 for (i
= 0; i
< RCC_NUM_CHANNEL_PLL_OUT
; i
++) {
251 s
->channels
[i
] = qdev_init_clock_out(DEVICE(s
), names
[i
]);
255 static void pll_reset_enter(Object
*obj
, ResetType type
)
257 RccPllState
*s
= RCC_PLL(obj
);
258 set_pll_init_info(s
, s
->id
);
261 static void pll_reset_hold(Object
*obj
)
263 RccPllState
*s
= RCC_PLL(obj
);
267 static void pll_reset_exit(Object
*obj
)
269 RccPllState
*s
= RCC_PLL(obj
);
270 pll_update(s
, false);
273 static const VMStateDescription pll_vmstate
= {
274 .name
= TYPE_RCC_PLL
,
276 .minimum_version_id
= 1,
277 .fields
= (VMStateField
[]) {
278 VMSTATE_UINT32(id
, RccPllState
),
279 VMSTATE_CLOCK(in
, RccPllState
),
280 VMSTATE_ARRAY_CLOCK(channels
, RccPllState
,
281 RCC_NUM_CHANNEL_PLL_OUT
),
282 VMSTATE_BOOL(enabled
, RccPllState
),
283 VMSTATE_UINT32(vco_multiplier
, RccPllState
),
284 VMSTATE_BOOL_ARRAY(channel_enabled
, RccPllState
, RCC_NUM_CHANNEL_PLL_OUT
),
285 VMSTATE_BOOL_ARRAY(channel_exists
, RccPllState
, RCC_NUM_CHANNEL_PLL_OUT
),
286 VMSTATE_UINT32_ARRAY(channel_divider
, RccPllState
, RCC_NUM_CHANNEL_PLL_OUT
),
287 VMSTATE_END_OF_LIST()
291 static void pll_class_init(ObjectClass
*klass
, void *data
)
293 DeviceClass
*dc
= DEVICE_CLASS(klass
);
294 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
296 rc
->phases
.enter
= pll_reset_enter
;
297 rc
->phases
.hold
= pll_reset_hold
;
298 rc
->phases
.exit
= pll_reset_exit
;
299 dc
->vmsd
= &pll_vmstate
;
302 static void pll_set_vco_multiplier(RccPllState
*pll
, uint32_t vco_multiplier
)
304 if (pll
->vco_multiplier
== vco_multiplier
) {
308 if (vco_multiplier
< 8 || vco_multiplier
> 86) {
309 qemu_log_mask(LOG_GUEST_ERROR
,
310 "%s: VCO multiplier is out of bound (%u) for PLL %u\n",
311 __func__
, vco_multiplier
, pll
->id
);
315 trace_stm32l4x5_rcc_pll_set_vco_multiplier(pll
->id
,
316 pll
->vco_multiplier
, vco_multiplier
);
318 pll
->vco_multiplier
= vco_multiplier
;
319 pll_update(pll
, false);
322 static void pll_set_enable(RccPllState
*pll
, bool enabled
)
324 if (pll
->enabled
== enabled
) {
328 pll
->enabled
= enabled
;
329 pll_update(pll
, false);
332 static void pll_set_channel_enable(RccPllState
*pll
,
333 PllCommonChannels channel
,
336 if (pll
->channel_enabled
[channel
] == enabled
) {
341 trace_stm32l4x5_rcc_pll_channel_enable(pll
->id
, channel
);
343 trace_stm32l4x5_rcc_pll_channel_disable(pll
->id
, channel
);
346 pll
->channel_enabled
[channel
] = enabled
;
347 pll_update(pll
, false);
350 static void pll_set_channel_divider(RccPllState
*pll
,
351 PllCommonChannels channel
,
354 if (pll
->channel_divider
[channel
] == divider
) {
358 trace_stm32l4x5_rcc_pll_set_channel_divider(pll
->id
,
359 channel
, pll
->channel_divider
[channel
], divider
);
361 pll
->channel_divider
[channel
] = divider
;
362 pll_update(pll
, false);
365 static void rcc_update_irq(Stm32l4x5RccState
*s
)
368 * TODO: Handle LSECSSF and CSSF flags when the CSS is implemented.
370 if (s
->cifr
& CIFR_IRQ_MASK
) {
371 qemu_irq_raise(s
->irq
);
373 qemu_irq_lower(s
->irq
);
377 static void rcc_update_msi(Stm32l4x5RccState
*s
, uint32_t previous_value
)
381 static const uint32_t msirange
[] = {
382 100000, 200000, 400000, 800000, 1000000, 2000000,
383 4000000, 8000000, 16000000, 24000000, 32000000, 48000000
385 /* MSIRANGE and MSIRGSEL */
386 val
= extract32(s
->cr
, R_CR_MSIRGSEL_SHIFT
, R_CR_MSIRGSEL_LENGTH
);
388 /* MSIRGSEL is set, use the MSIRANGE field */
389 val
= extract32(s
->cr
, R_CR_MSIRANGE_SHIFT
, R_CR_MSIRANGE_LENGTH
);
391 /* MSIRGSEL is not set, use the MSISRANGE field */
392 val
= extract32(s
->csr
, R_CSR_MSISRANGE_SHIFT
, R_CSR_MSISRANGE_LENGTH
);
395 if (val
< ARRAY_SIZE(msirange
)) {
396 clock_update_hz(s
->msi_rc
, msirange
[val
]);
399 * There is a hardware write protection if the value is out of bound.
400 * Restore the previous value.
402 s
->cr
= (s
->cr
& ~R_CSR_MSISRANGE_MASK
) |
403 (previous_value
& R_CSR_MSISRANGE_MASK
);
408 * TODO: Add write-protection for all registers:
412 static void rcc_update_cr_register(Stm32l4x5RccState
*s
, uint32_t previous_value
)
415 const RccClockMuxSource current_pll_src
=
416 CLOCK_MUX_INIT_INFO
[RCC_CLOCK_MUX_PLL_INPUT
].src_mapping
[
417 s
->clock_muxes
[RCC_CLOCK_MUX_PLL_INPUT
].src
];
419 /* PLLSAI2ON and update PLLSAI2RDY */
420 val
= FIELD_EX32(s
->cr
, CR
, PLLSAI2ON
);
421 pll_set_enable(&s
->plls
[RCC_PLL_PLLSAI2
], val
);
422 s
->cr
= (s
->cr
& ~R_CR_PLLSAI2RDY_MASK
) |
423 (val
<< R_CR_PLLSAI2RDY_SHIFT
);
424 if (s
->cier
& R_CIER_PLLSAI2RDYIE_MASK
) {
425 s
->cifr
|= R_CIFR_PLLSAI2RDYF_MASK
;
428 /* PLLSAI1ON and update PLLSAI1RDY */
429 val
= FIELD_EX32(s
->cr
, CR
, PLLSAI1ON
);
430 pll_set_enable(&s
->plls
[RCC_PLL_PLLSAI1
], val
);
431 s
->cr
= (s
->cr
& ~R_CR_PLLSAI1RDY_MASK
) |
432 (val
<< R_CR_PLLSAI1RDY_SHIFT
);
433 if (s
->cier
& R_CIER_PLLSAI1RDYIE_MASK
) {
434 s
->cifr
|= R_CIFR_PLLSAI1RDYF_MASK
;
438 * PLLON and update PLLRDY
439 * PLLON cannot be reset if the PLL clock is used as the system clock.
441 val
= FIELD_EX32(s
->cr
, CR
, PLLON
);
442 if (FIELD_EX32(s
->cfgr
, CFGR
, SWS
) != 0b11) {
443 pll_set_enable(&s
->plls
[RCC_PLL_PLL
], val
);
444 s
->cr
= (s
->cr
& ~R_CR_PLLRDY_MASK
) |
445 (val
<< R_CR_PLLRDY_SHIFT
);
446 if (s
->cier
& R_CIER_PLLRDYIE_MASK
) {
447 s
->cifr
|= R_CIFR_PLLRDYF_MASK
;
450 s
->cr
|= R_CR_PLLON_MASK
;
457 * HSEON and update HSERDY.
458 * HSEON cannot be reset if the HSE oscillator is used directly or
459 * indirectly as the system clock.
461 val
= FIELD_EX32(s
->cr
, CR
, HSEON
);
462 if (FIELD_EX32(s
->cfgr
, CFGR
, SWS
) != 0b10 &&
463 current_pll_src
!= RCC_CLOCK_MUX_SRC_HSE
) {
464 s
->cr
= (s
->cr
& ~R_CR_HSERDY_MASK
) |
465 (val
<< R_CR_HSERDY_SHIFT
);
467 clock_update_hz(s
->hse
, s
->hse_frequency
);
468 if (s
->cier
& R_CIER_HSERDYIE_MASK
) {
469 s
->cifr
|= R_CIFR_HSERDYF_MASK
;
472 clock_update(s
->hse
, 0);
475 s
->cr
|= R_CR_HSEON_MASK
;
482 * HSION and update HSIRDY
483 * HSION is set by hardware if the HSI16 is used directly
484 * or indirectly as system clock.
486 if (FIELD_EX32(s
->cfgr
, CFGR
, SWS
) == 0b01 ||
487 current_pll_src
== RCC_CLOCK_MUX_SRC_HSI
) {
488 s
->cr
|= (R_CR_HSION_MASK
| R_CR_HSIRDY_MASK
);
489 clock_update_hz(s
->hsi16_rc
, HSI_FRQ
);
490 if (s
->cier
& R_CIER_HSIRDYIE_MASK
) {
491 s
->cifr
|= R_CIFR_HSIRDYF_MASK
;
494 val
= FIELD_EX32(s
->cr
, CR
, HSION
);
496 clock_update_hz(s
->hsi16_rc
, HSI_FRQ
);
497 s
->cr
|= R_CR_HSIRDY_MASK
;
498 if (s
->cier
& R_CIER_HSIRDYIE_MASK
) {
499 s
->cifr
|= R_CIFR_HSIRDYF_MASK
;
502 clock_update(s
->hsi16_rc
, 0);
503 s
->cr
&= ~R_CR_HSIRDY_MASK
;
510 * MSION and update MSIRDY
511 * Set by hardware when used directly or indirectly as system clock.
513 if (FIELD_EX32(s
->cfgr
, CFGR
, SWS
) == 0b00 ||
514 current_pll_src
== RCC_CLOCK_MUX_SRC_MSI
) {
515 s
->cr
|= (R_CR_MSION_MASK
| R_CR_MSIRDY_MASK
);
516 if (!(previous_value
& R_CR_MSION_MASK
) && (s
->cier
& R_CIER_MSIRDYIE_MASK
)) {
517 s
->cifr
|= R_CIFR_MSIRDYF_MASK
;
519 rcc_update_msi(s
, previous_value
);
521 val
= FIELD_EX32(s
->cr
, CR
, MSION
);
523 s
->cr
|= R_CR_MSIRDY_MASK
;
524 rcc_update_msi(s
, previous_value
);
525 if (s
->cier
& R_CIER_MSIRDYIE_MASK
) {
526 s
->cifr
|= R_CIFR_MSIRDYF_MASK
;
529 s
->cr
&= ~R_CR_MSIRDY_MASK
;
530 clock_update(s
->msi_rc
, 0);
536 static void rcc_update_cfgr_register(Stm32l4x5RccState
*s
)
540 val
= FIELD_EX32(s
->cfgr
, CFGR
, MCOPRE
);
541 assert(val
<= 0b100);
542 clock_mux_set_factor(&s
->clock_muxes
[RCC_CLOCK_MUX_MCO
],
546 val
= FIELD_EX32(s
->cfgr
, CFGR
, MCOSEL
);
547 assert(val
<= 0b111);
549 clock_mux_set_enable(&s
->clock_muxes
[RCC_CLOCK_MUX_MCO
], false);
551 clock_mux_set_enable(&s
->clock_muxes
[RCC_CLOCK_MUX_MCO
], true);
552 clock_mux_set_source(&s
->clock_muxes
[RCC_CLOCK_MUX_MCO
],
560 val
= FIELD_EX32(s
->cfgr
, CFGR
, PPRE2
);
562 clock_mux_set_factor(&s
->clock_muxes
[RCC_CLOCK_MUX_PCLK2
],
565 clock_mux_set_factor(&s
->clock_muxes
[RCC_CLOCK_MUX_PCLK2
],
566 1, 1 << (val
- 0b11));
570 val
= FIELD_EX32(s
->cfgr
, CFGR
, PPRE1
);
572 clock_mux_set_factor(&s
->clock_muxes
[RCC_CLOCK_MUX_PCLK1
],
575 clock_mux_set_factor(&s
->clock_muxes
[RCC_CLOCK_MUX_PCLK1
],
576 1, 1 << (val
- 0b11));
580 val
= FIELD_EX32(s
->cfgr
, CFGR
, HPRE
);
582 clock_mux_set_factor(&s
->clock_muxes
[RCC_CLOCK_MUX_HCLK
],
585 clock_mux_set_factor(&s
->clock_muxes
[RCC_CLOCK_MUX_HCLK
],
586 1, 1 << (val
- 0b111));
590 val
= FIELD_EX32(s
->cfgr
, CFGR
, SW
);
591 clock_mux_set_source(&s
->clock_muxes
[RCC_CLOCK_MUX_SYSCLK
],
593 s
->cfgr
&= ~R_CFGR_SWS_MASK
;
594 s
->cfgr
|= val
<< R_CFGR_SWS_SHIFT
;
597 static void rcc_update_ahb1enr(Stm32l4x5RccState
*s
)
599 #define AHB1ENR_SET_ENABLE(_peripheral_name) \
600 clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
601 FIELD_EX32(s->ahb1enr, AHB1ENR, _peripheral_name##EN))
603 /* DMA2DEN: reserved for STM32L475xx */
604 AHB1ENR_SET_ENABLE(TSC
);
605 AHB1ENR_SET_ENABLE(CRC
);
606 AHB1ENR_SET_ENABLE(FLASH
);
607 AHB1ENR_SET_ENABLE(DMA2
);
608 AHB1ENR_SET_ENABLE(DMA1
);
610 #undef AHB1ENR_SET_ENABLE
613 static void rcc_update_ahb2enr(Stm32l4x5RccState
*s
)
615 #define AHB2ENR_SET_ENABLE(_peripheral_name) \
616 clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
617 FIELD_EX32(s->ahb2enr, AHB2ENR, _peripheral_name##EN))
619 AHB2ENR_SET_ENABLE(RNG
);
620 /* HASHEN: reserved for STM32L475xx */
621 AHB2ENR_SET_ENABLE(AES
);
622 /* DCMIEN: reserved for STM32L475xx */
623 AHB2ENR_SET_ENABLE(ADC
);
624 AHB2ENR_SET_ENABLE(OTGFS
);
625 /* GPIOIEN: reserved for STM32L475xx */
626 AHB2ENR_SET_ENABLE(GPIOA
);
627 AHB2ENR_SET_ENABLE(GPIOB
);
628 AHB2ENR_SET_ENABLE(GPIOC
);
629 AHB2ENR_SET_ENABLE(GPIOD
);
630 AHB2ENR_SET_ENABLE(GPIOE
);
631 AHB2ENR_SET_ENABLE(GPIOF
);
632 AHB2ENR_SET_ENABLE(GPIOG
);
633 AHB2ENR_SET_ENABLE(GPIOH
);
635 #undef AHB2ENR_SET_ENABLE
638 static void rcc_update_ahb3enr(Stm32l4x5RccState
*s
)
640 #define AHB3ENR_SET_ENABLE(_peripheral_name) \
641 clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
642 FIELD_EX32(s->ahb3enr, AHB3ENR, _peripheral_name##EN))
644 AHB3ENR_SET_ENABLE(QSPI
);
645 AHB3ENR_SET_ENABLE(FMC
);
647 #undef AHB3ENR_SET_ENABLE
650 static void rcc_update_apb1enr(Stm32l4x5RccState
*s
)
652 #define APB1ENR1_SET_ENABLE(_peripheral_name) \
653 clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
654 FIELD_EX32(s->apb1enr1, APB1ENR1, _peripheral_name##EN))
655 #define APB1ENR2_SET_ENABLE(_peripheral_name) \
656 clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
657 FIELD_EX32(s->apb1enr2, APB1ENR2, _peripheral_name##EN))
660 APB1ENR1_SET_ENABLE(LPTIM1
);
661 APB1ENR1_SET_ENABLE(OPAMP
);
662 APB1ENR1_SET_ENABLE(DAC1
);
663 APB1ENR1_SET_ENABLE(PWR
);
664 /* CAN2: reserved for STM32L4x5 */
665 APB1ENR1_SET_ENABLE(CAN1
);
666 /* CRSEN: reserved for STM32L4x5 */
667 APB1ENR1_SET_ENABLE(I2C3
);
668 APB1ENR1_SET_ENABLE(I2C2
);
669 APB1ENR1_SET_ENABLE(I2C1
);
670 APB1ENR1_SET_ENABLE(UART5
);
671 APB1ENR1_SET_ENABLE(UART4
);
672 APB1ENR1_SET_ENABLE(USART3
);
673 APB1ENR1_SET_ENABLE(USART2
);
674 APB1ENR1_SET_ENABLE(SPI3
);
675 APB1ENR1_SET_ENABLE(SPI2
);
676 APB1ENR1_SET_ENABLE(WWDG
);
677 /* RTCAPB: reserved for STM32L4x5 */
678 APB1ENR1_SET_ENABLE(LCD
);
679 APB1ENR1_SET_ENABLE(TIM7
);
680 APB1ENR1_SET_ENABLE(TIM6
);
681 APB1ENR1_SET_ENABLE(TIM5
);
682 APB1ENR1_SET_ENABLE(TIM4
);
683 APB1ENR1_SET_ENABLE(TIM3
);
684 APB1ENR1_SET_ENABLE(TIM2
);
687 APB1ENR2_SET_ENABLE(LPTIM2
);
688 APB1ENR2_SET_ENABLE(SWPMI1
);
689 /* I2C4EN: reserved for STM32L4x5 */
690 APB1ENR2_SET_ENABLE(LPUART1
);
692 #undef APB1ENR1_SET_ENABLE
693 #undef APB1ENR2_SET_ENABLE
696 static void rcc_update_apb2enr(Stm32l4x5RccState
*s
)
698 #define APB2ENR_SET_ENABLE(_peripheral_name) \
699 clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
700 FIELD_EX32(s->apb2enr, APB2ENR, _peripheral_name##EN))
702 APB2ENR_SET_ENABLE(DFSDM1
);
703 APB2ENR_SET_ENABLE(SAI2
);
704 APB2ENR_SET_ENABLE(SAI1
);
705 APB2ENR_SET_ENABLE(TIM17
);
706 APB2ENR_SET_ENABLE(TIM16
);
707 APB2ENR_SET_ENABLE(TIM15
);
708 APB2ENR_SET_ENABLE(USART1
);
709 APB2ENR_SET_ENABLE(TIM8
);
710 APB2ENR_SET_ENABLE(SPI1
);
711 APB2ENR_SET_ENABLE(TIM1
);
712 APB2ENR_SET_ENABLE(SDMMC1
);
713 APB2ENR_SET_ENABLE(FW
);
714 APB2ENR_SET_ENABLE(SYSCFG
);
716 #undef APB2ENR_SET_ENABLE
720 * The 3 PLLs share the same register layout
721 * so we can use the same function for all of them
722 * Note: no frequency bounds checking is done here.
724 static void rcc_update_pllsaixcfgr(Stm32l4x5RccState
*s
, RccPll pll_id
)
731 case RCC_PLL_PLLSAI1
:
732 reg
= s
->pllsai1cfgr
;
734 case RCC_PLL_PLLSAI2
:
735 reg
= s
->pllsai2cfgr
;
738 qemu_log_mask(LOG_GUEST_ERROR
,
739 "%s: Invalid PLL ID: %u\n", __func__
, pll_id
);
744 val
= FIELD_EX32(reg
, PLLCFGR
, PLLPDIV
);
745 /* 1 is a reserved value */
748 val
= FIELD_EX32(reg
, PLLCFGR
, PLLP
);
749 pll_set_channel_divider(&s
->plls
[pll_id
], RCC_PLL_COMMON_CHANNEL_P
,
751 } else if (val
> 1) {
752 pll_set_channel_divider(&s
->plls
[pll_id
], RCC_PLL_COMMON_CHANNEL_P
,
758 val
= FIELD_EX32(reg
, PLLCFGR
, PLLR
);
759 pll_set_channel_divider(&s
->plls
[pll_id
], RCC_PLL_COMMON_CHANNEL_R
,
763 val
= FIELD_EX32(reg
, PLLCFGR
, PLLREN
);
764 pll_set_channel_enable(&s
->plls
[pll_id
], RCC_PLL_COMMON_CHANNEL_R
, val
);
767 val
= FIELD_EX32(reg
, PLLCFGR
, PLLQ
);
768 pll_set_channel_divider(&s
->plls
[pll_id
], RCC_PLL_COMMON_CHANNEL_Q
,
772 val
= FIELD_EX32(reg
, PLLCFGR
, PLLQEN
);
773 pll_set_channel_enable(&s
->plls
[pll_id
], RCC_PLL_COMMON_CHANNEL_Q
, val
);
776 val
= FIELD_EX32(reg
, PLLCFGR
, PLLPEN
);
777 pll_set_channel_enable(&s
->plls
[pll_id
], RCC_PLL_COMMON_CHANNEL_P
, val
);
780 val
= FIELD_EX32(reg
, PLLCFGR
, PLLN
);
781 pll_set_vco_multiplier(&s
->plls
[pll_id
], val
);
784 static void rcc_update_pllcfgr(Stm32l4x5RccState
*s
)
788 /* Use common layout */
789 rcc_update_pllsaixcfgr(s
, RCC_PLL_PLL
);
791 /* Fetch specific fields for pllcfgr */
794 val
= FIELD_EX32(s
->pllcfgr
, PLLCFGR
, PLLM
);
795 clock_mux_set_factor(&s
->clock_muxes
[RCC_CLOCK_MUX_PLL_INPUT
], 1, (val
+ 1));
798 val
= FIELD_EX32(s
->pllcfgr
, PLLCFGR
, PLLSRC
);
800 clock_mux_set_enable(&s
->clock_muxes
[RCC_CLOCK_MUX_PLL_INPUT
], false);
802 clock_mux_set_source(&s
->clock_muxes
[RCC_CLOCK_MUX_PLL_INPUT
], val
- 1);
803 clock_mux_set_enable(&s
->clock_muxes
[RCC_CLOCK_MUX_PLL_INPUT
], true);
807 static void rcc_update_ccipr(Stm32l4x5RccState
*s
)
809 #define CCIPR_SET_SOURCE(_peripheral_name) \
810 clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
811 FIELD_EX32(s->ccipr, CCIPR, _peripheral_name##SEL))
813 CCIPR_SET_SOURCE(DFSDM1
);
814 CCIPR_SET_SOURCE(SWPMI1
);
815 CCIPR_SET_SOURCE(ADC
);
816 CCIPR_SET_SOURCE(CLK48
);
817 CCIPR_SET_SOURCE(SAI2
);
818 CCIPR_SET_SOURCE(SAI1
);
819 CCIPR_SET_SOURCE(LPTIM2
);
820 CCIPR_SET_SOURCE(LPTIM1
);
821 CCIPR_SET_SOURCE(I2C3
);
822 CCIPR_SET_SOURCE(I2C2
);
823 CCIPR_SET_SOURCE(I2C1
);
824 CCIPR_SET_SOURCE(LPUART1
);
825 CCIPR_SET_SOURCE(UART5
);
826 CCIPR_SET_SOURCE(UART4
);
827 CCIPR_SET_SOURCE(USART3
);
828 CCIPR_SET_SOURCE(USART2
);
829 CCIPR_SET_SOURCE(USART1
);
831 #undef CCIPR_SET_SOURCE
834 static void rcc_update_bdcr(Stm32l4x5RccState
*s
)
839 val
= FIELD_EX32(s
->bdcr
, BDCR
, LSCOSEL
);
840 clock_mux_set_source(&s
->clock_muxes
[RCC_CLOCK_MUX_LSCO
], val
);
842 val
= FIELD_EX32(s
->bdcr
, BDCR
, LSCOEN
);
843 clock_mux_set_enable(&s
->clock_muxes
[RCC_CLOCK_MUX_LSCO
], val
);
847 * The documentation is not clear if the RTCEN flag disables the RTC and
848 * the LCD common mux or if it only affects the RTC.
849 * As the LCDEN flag exists, we assume here that it only affects the RTC.
851 val
= FIELD_EX32(s
->bdcr
, BDCR
, RTCEN
);
852 clock_mux_set_enable(&s
->clock_muxes
[RCC_CLOCK_MUX_RTC
], val
);
853 /* LCD and RTC share the same clock */
854 val
= FIELD_EX32(s
->bdcr
, BDCR
, RTCSEL
);
855 clock_mux_set_source(&s
->clock_muxes
[RCC_CLOCK_MUX_LCD_AND_RTC_COMMON
], val
);
861 /* LSEON: Update LSERDY at the same time */
862 val
= FIELD_EX32(s
->bdcr
, BDCR
, LSEON
);
864 clock_update_hz(s
->lse_crystal
, LSE_FRQ
);
865 s
->bdcr
|= R_BDCR_LSERDY_MASK
;
866 if (s
->cier
& R_CIER_LSERDYIE_MASK
) {
867 s
->cifr
|= R_CIFR_LSERDYF_MASK
;
870 clock_update(s
->lse_crystal
, 0);
871 s
->bdcr
&= ~R_BDCR_LSERDY_MASK
;
877 static void rcc_update_csr(Stm32l4x5RccState
*s
)
881 /* Reset flags: Not implemented */
882 /* MSISRANGE: Not implemented after reset */
884 /* LSION: Update LSIRDY at the same time */
885 val
= FIELD_EX32(s
->csr
, CSR
, LSION
);
887 clock_update_hz(s
->lsi_rc
, LSI_FRQ
);
888 s
->csr
|= R_CSR_LSIRDY_MASK
;
889 if (s
->cier
& R_CIER_LSIRDYIE_MASK
) {
890 s
->cifr
|= R_CIFR_LSIRDYF_MASK
;
894 * TODO: Handle when the LSI is set independently of LSION.
895 * E.g. when the LSI is set by the RTC.
896 * See the reference manual for more details.
898 clock_update(s
->lsi_rc
, 0);
899 s
->csr
&= ~R_CSR_LSIRDY_MASK
;
905 static void stm32l4x5_rcc_reset_hold(Object
*obj
)
907 Stm32l4x5RccState
*s
= STM32L4X5_RCC(obj
);
910 * Factory-programmed calibration data
911 * From the reference manual: 0x10XX 00XX
912 * Value taken from a real card.
914 s
->icscr
= 0x106E0082;
916 s
->pllcfgr
= 0x00001000;
917 s
->pllsai1cfgr
= 0x00001000;
918 s
->pllsai2cfgr
= 0x00001000;
927 s
->ahb1enr
= 0x00000100;
933 s
->ahb1smenr
= 0x00011303;
934 s
->ahb2smenr
= 0x000532FF;
935 s
->ahb3smenr
= 0x00000101;
936 s
->apb1smenr1
= 0xF2FECA3F;
937 s
->apb1smenr2
= 0x00000025;
938 s
->apb2smenr
= 0x01677C01;
944 static uint64_t stm32l4x5_rcc_read(void *opaque
, hwaddr addr
,
947 Stm32l4x5RccState
*s
= opaque
;
948 uint64_t retvalue
= 0;
961 retvalue
= s
->pllcfgr
;
964 retvalue
= s
->pllsai1cfgr
;
967 retvalue
= s
->pllsai2cfgr
;
976 /* CICR is write only, return the reset value = 0 */
979 retvalue
= s
->ahb1rstr
;
982 retvalue
= s
->ahb2rstr
;
985 retvalue
= s
->ahb3rstr
;
988 retvalue
= s
->apb1rstr1
;
991 retvalue
= s
->apb1rstr2
;
994 retvalue
= s
->apb2rstr
;
997 retvalue
= s
->ahb1enr
;
1000 retvalue
= s
->ahb2enr
;
1003 retvalue
= s
->ahb3enr
;
1006 retvalue
= s
->apb1enr1
;
1009 retvalue
= s
->apb1enr2
;
1012 retvalue
= s
->apb2enr
;
1015 retvalue
= s
->ahb1smenr
;
1018 retvalue
= s
->ahb2smenr
;
1021 retvalue
= s
->ahb3smenr
;
1024 retvalue
= s
->apb1smenr1
;
1027 retvalue
= s
->apb1smenr2
;
1030 retvalue
= s
->apb2smenr
;
1033 retvalue
= s
->ccipr
;
1042 qemu_log_mask(LOG_GUEST_ERROR
,
1043 "%s: Bad offset 0x%"HWADDR_PRIx
"\n", __func__
, addr
);
1047 trace_stm32l4x5_rcc_read(addr
, retvalue
);
1052 static void stm32l4x5_rcc_write(void *opaque
, hwaddr addr
,
1053 uint64_t val64
, unsigned int size
)
1055 Stm32l4x5RccState
*s
= opaque
;
1056 uint32_t previous_value
= 0;
1057 const uint32_t value
= val64
;
1059 trace_stm32l4x5_rcc_write(addr
, value
);
1063 previous_value
= s
->cr
;
1064 s
->cr
= (s
->cr
& CR_READ_SET_MASK
) |
1065 (value
& (CR_READ_SET_MASK
| ~CR_READ_ONLY_MASK
));
1066 rcc_update_cr_register(s
, previous_value
);
1069 s
->icscr
= value
& ~ICSCR_READ_ONLY_MASK
;
1070 qemu_log_mask(LOG_UNIMP
,
1071 "%s: Side-effects not implemented for ICSCR\n", __func__
);
1074 s
->cfgr
= value
& ~CFGR_READ_ONLY_MASK
;
1075 rcc_update_cfgr_register(s
);
1079 rcc_update_pllcfgr(s
);
1082 s
->pllsai1cfgr
= value
;
1083 rcc_update_pllsaixcfgr(s
, RCC_PLL_PLLSAI1
);
1086 s
->pllsai2cfgr
= value
;
1087 rcc_update_pllsaixcfgr(s
, RCC_PLL_PLLSAI2
);
1091 qemu_log_mask(LOG_UNIMP
,
1092 "%s: Side-effects not implemented for CIER\n", __func__
);
1095 qemu_log_mask(LOG_GUEST_ERROR
,
1096 "%s: Write attempt into read-only register (CIFR) 0x%"PRIx32
"\n",
1100 /* Clear interrupt flags by writing a 1 to the CICR register */
1104 /* Reset behaviors are not implemented */
1106 s
->ahb1rstr
= value
;
1107 qemu_log_mask(LOG_UNIMP
,
1108 "%s: Side-effects not implemented for AHB1RSTR\n", __func__
);
1111 s
->ahb2rstr
= value
;
1112 qemu_log_mask(LOG_UNIMP
,
1113 "%s: Side-effects not implemented for AHB2RSTR\n", __func__
);
1116 s
->ahb3rstr
= value
;
1117 qemu_log_mask(LOG_UNIMP
,
1118 "%s: Side-effects not implemented for AHB3RSTR\n", __func__
);
1121 s
->apb1rstr1
= value
;
1122 qemu_log_mask(LOG_UNIMP
,
1123 "%s: Side-effects not implemented for APB1RSTR1\n", __func__
);
1126 s
->apb1rstr2
= value
;
1127 qemu_log_mask(LOG_UNIMP
,
1128 "%s: Side-effects not implemented for APB1RSTR2\n", __func__
);
1131 s
->apb2rstr
= value
;
1132 qemu_log_mask(LOG_UNIMP
,
1133 "%s: Side-effects not implemented for APB2RSTR\n", __func__
);
1137 rcc_update_ahb1enr(s
);
1141 rcc_update_ahb2enr(s
);
1145 rcc_update_ahb3enr(s
);
1148 s
->apb1enr1
= value
;
1149 rcc_update_apb1enr(s
);
1152 s
->apb1enr2
= value
;
1153 rcc_update_apb1enr(s
);
1156 s
->apb2enr
= (s
->apb2enr
& APB2ENR_READ_SET_MASK
) | value
;
1157 rcc_update_apb2enr(s
);
1159 /* Behaviors for Sleep and Stop modes are not implemented */
1161 s
->ahb1smenr
= value
;
1162 qemu_log_mask(LOG_UNIMP
,
1163 "%s: Side-effects not implemented for AHB1SMENR\n", __func__
);
1166 s
->ahb2smenr
= value
;
1167 qemu_log_mask(LOG_UNIMP
,
1168 "%s: Side-effects not implemented for AHB2SMENR\n", __func__
);
1171 s
->ahb3smenr
= value
;
1172 qemu_log_mask(LOG_UNIMP
,
1173 "%s: Side-effects not implemented for AHB3SMENR\n", __func__
);
1176 s
->apb1smenr1
= value
;
1177 qemu_log_mask(LOG_UNIMP
,
1178 "%s: Side-effects not implemented for APB1SMENR1\n", __func__
);
1181 s
->apb1smenr2
= value
;
1182 qemu_log_mask(LOG_UNIMP
,
1183 "%s: Side-effects not implemented for APB1SMENR2\n", __func__
);
1186 s
->apb2smenr
= value
;
1187 qemu_log_mask(LOG_UNIMP
,
1188 "%s: Side-effects not implemented for APB2SMENR\n", __func__
);
1192 rcc_update_ccipr(s
);
1195 s
->bdcr
= value
& ~BDCR_READ_ONLY_MASK
;
1199 s
->csr
= value
& ~CSR_READ_ONLY_MASK
;
1203 qemu_log_mask(LOG_GUEST_ERROR
,
1204 "%s: Bad offset 0x%"HWADDR_PRIx
"\n", __func__
, addr
);
1208 static const MemoryRegionOps stm32l4x5_rcc_ops
= {
1209 .read
= stm32l4x5_rcc_read
,
1210 .write
= stm32l4x5_rcc_write
,
1211 .endianness
= DEVICE_NATIVE_ENDIAN
,
1213 .max_access_size
= 4,
1214 .min_access_size
= 4,
1218 .max_access_size
= 4,
1219 .min_access_size
= 4,
1224 static const ClockPortInitArray stm32l4x5_rcc_clocks
= {
1225 QDEV_CLOCK_IN(Stm32l4x5RccState
, hsi16_rc
, NULL
, 0),
1226 QDEV_CLOCK_IN(Stm32l4x5RccState
, msi_rc
, NULL
, 0),
1227 QDEV_CLOCK_IN(Stm32l4x5RccState
, hse
, NULL
, 0),
1228 QDEV_CLOCK_IN(Stm32l4x5RccState
, lsi_rc
, NULL
, 0),
1229 QDEV_CLOCK_IN(Stm32l4x5RccState
, lse_crystal
, NULL
, 0),
1230 QDEV_CLOCK_IN(Stm32l4x5RccState
, sai1_extclk
, NULL
, 0),
1231 QDEV_CLOCK_IN(Stm32l4x5RccState
, sai2_extclk
, NULL
, 0),
1236 static void stm32l4x5_rcc_init(Object
*obj
)
1238 Stm32l4x5RccState
*s
= STM32L4X5_RCC(obj
);
1241 sysbus_init_irq(SYS_BUS_DEVICE(obj
), &s
->irq
);
1243 memory_region_init_io(&s
->mmio
, obj
, &stm32l4x5_rcc_ops
, s
,
1244 TYPE_STM32L4X5_RCC
, 0x400);
1245 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &s
->mmio
);
1247 qdev_init_clocks(DEVICE(s
), stm32l4x5_rcc_clocks
);
1249 for (i
= 0; i
< RCC_NUM_PLL
; i
++) {
1250 object_initialize_child(obj
, PLL_INIT_INFO
[i
].name
,
1251 &s
->plls
[i
], TYPE_RCC_PLL
);
1252 set_pll_init_info(&s
->plls
[i
], i
);
1255 for (i
= 0; i
< RCC_NUM_CLOCK_MUX
; i
++) {
1258 object_initialize_child(obj
, CLOCK_MUX_INIT_INFO
[i
].name
,
1260 TYPE_RCC_CLOCK_MUX
);
1261 set_clock_mux_init_info(&s
->clock_muxes
[i
], i
);
1263 if (!CLOCK_MUX_INIT_INFO
[i
].hidden
) {
1264 /* Expose muxes output as RCC outputs */
1265 alias
= g_strdup_printf("%s-out", CLOCK_MUX_INIT_INFO
[i
].name
);
1266 qdev_alias_clock(DEVICE(&s
->clock_muxes
[i
]), "out", DEVICE(obj
), alias
);
1271 s
->gnd
= clock_new(obj
, "gnd");
1274 static void connect_mux_sources(Stm32l4x5RccState
*s
,
1275 RccClockMuxState
*mux
,
1276 const RccClockMuxSource
*clk_mapping
)
1280 Clock
* const CLK_SRC_MAPPING
[] = {
1281 [RCC_CLOCK_MUX_SRC_GND
] = s
->gnd
,
1282 [RCC_CLOCK_MUX_SRC_HSI
] = s
->hsi16_rc
,
1283 [RCC_CLOCK_MUX_SRC_HSE
] = s
->hse
,
1284 [RCC_CLOCK_MUX_SRC_MSI
] = s
->msi_rc
,
1285 [RCC_CLOCK_MUX_SRC_LSI
] = s
->lsi_rc
,
1286 [RCC_CLOCK_MUX_SRC_LSE
] = s
->lse_crystal
,
1287 [RCC_CLOCK_MUX_SRC_SAI1_EXTCLK
] = s
->sai1_extclk
,
1288 [RCC_CLOCK_MUX_SRC_SAI2_EXTCLK
] = s
->sai2_extclk
,
1289 [RCC_CLOCK_MUX_SRC_PLL
] =
1290 s
->plls
[RCC_PLL_PLL
].channels
[RCC_PLL_CHANNEL_PLLCLK
],
1291 [RCC_CLOCK_MUX_SRC_PLLSAI1
] =
1292 s
->plls
[RCC_PLL_PLLSAI1
].channels
[RCC_PLLSAI1_CHANNEL_PLLSAI1CLK
],
1293 [RCC_CLOCK_MUX_SRC_PLLSAI2
] =
1294 s
->plls
[RCC_PLL_PLLSAI2
].channels
[RCC_PLLSAI2_CHANNEL_PLLSAI2CLK
],
1295 [RCC_CLOCK_MUX_SRC_PLLSAI3
] =
1296 s
->plls
[RCC_PLL_PLL
].channels
[RCC_PLL_CHANNEL_PLLSAI3CLK
],
1297 [RCC_CLOCK_MUX_SRC_PLL48M1
] =
1298 s
->plls
[RCC_PLL_PLL
].channels
[RCC_PLL_CHANNEL_PLL48M1CLK
],
1299 [RCC_CLOCK_MUX_SRC_PLL48M2
] =
1300 s
->plls
[RCC_PLL_PLLSAI1
].channels
[RCC_PLLSAI1_CHANNEL_PLL48M2CLK
],
1301 [RCC_CLOCK_MUX_SRC_PLLADC1
] =
1302 s
->plls
[RCC_PLL_PLLSAI1
].channels
[RCC_PLLSAI1_CHANNEL_PLLADC1CLK
],
1303 [RCC_CLOCK_MUX_SRC_PLLADC2
] =
1304 s
->plls
[RCC_PLL_PLLSAI2
] .channels
[RCC_PLLSAI2_CHANNEL_PLLADC2CLK
],
1305 [RCC_CLOCK_MUX_SRC_SYSCLK
] = s
->clock_muxes
[RCC_CLOCK_MUX_SYSCLK
].out
,
1306 [RCC_CLOCK_MUX_SRC_HCLK
] = s
->clock_muxes
[RCC_CLOCK_MUX_HCLK
].out
,
1307 [RCC_CLOCK_MUX_SRC_PCLK1
] = s
->clock_muxes
[RCC_CLOCK_MUX_PCLK1
].out
,
1308 [RCC_CLOCK_MUX_SRC_PCLK2
] = s
->clock_muxes
[RCC_CLOCK_MUX_PCLK2
].out
,
1309 [RCC_CLOCK_MUX_SRC_HSE_OVER_32
] = s
->clock_muxes
[RCC_CLOCK_MUX_HSE_OVER_32
].out
,
1310 [RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON
] =
1311 s
->clock_muxes
[RCC_CLOCK_MUX_LCD_AND_RTC_COMMON
].out
,
1314 assert(ARRAY_SIZE(CLK_SRC_MAPPING
) == RCC_CLOCK_MUX_SRC_NUMBER
);
1316 for (i
= 0; i
< RCC_NUM_CLOCK_MUX_SRC
; i
++) {
1317 RccClockMuxSource mapping
= clk_mapping
[i
];
1318 clock_set_source(mux
->srcs
[i
], CLK_SRC_MAPPING
[mapping
]);
1323 static const VMStateDescription vmstate_stm32l4x5_rcc
= {
1324 .name
= TYPE_STM32L4X5_RCC
,
1326 .minimum_version_id
= 1,
1327 .fields
= (VMStateField
[]) {
1328 VMSTATE_UINT32(cr
, Stm32l4x5RccState
),
1329 VMSTATE_UINT32(icscr
, Stm32l4x5RccState
),
1330 VMSTATE_UINT32(cfgr
, Stm32l4x5RccState
),
1331 VMSTATE_UINT32(pllcfgr
, Stm32l4x5RccState
),
1332 VMSTATE_UINT32(pllsai1cfgr
, Stm32l4x5RccState
),
1333 VMSTATE_UINT32(pllsai2cfgr
, Stm32l4x5RccState
),
1334 VMSTATE_UINT32(cier
, Stm32l4x5RccState
),
1335 VMSTATE_UINT32(cifr
, Stm32l4x5RccState
),
1336 VMSTATE_UINT32(ahb1rstr
, Stm32l4x5RccState
),
1337 VMSTATE_UINT32(ahb2rstr
, Stm32l4x5RccState
),
1338 VMSTATE_UINT32(ahb3rstr
, Stm32l4x5RccState
),
1339 VMSTATE_UINT32(apb1rstr1
, Stm32l4x5RccState
),
1340 VMSTATE_UINT32(apb1rstr2
, Stm32l4x5RccState
),
1341 VMSTATE_UINT32(apb2rstr
, Stm32l4x5RccState
),
1342 VMSTATE_UINT32(ahb1enr
, Stm32l4x5RccState
),
1343 VMSTATE_UINT32(ahb2enr
, Stm32l4x5RccState
),
1344 VMSTATE_UINT32(ahb3enr
, Stm32l4x5RccState
),
1345 VMSTATE_UINT32(apb1enr1
, Stm32l4x5RccState
),
1346 VMSTATE_UINT32(apb1enr2
, Stm32l4x5RccState
),
1347 VMSTATE_UINT32(apb2enr
, Stm32l4x5RccState
),
1348 VMSTATE_UINT32(ahb1smenr
, Stm32l4x5RccState
),
1349 VMSTATE_UINT32(ahb2smenr
, Stm32l4x5RccState
),
1350 VMSTATE_UINT32(ahb3smenr
, Stm32l4x5RccState
),
1351 VMSTATE_UINT32(apb1smenr1
, Stm32l4x5RccState
),
1352 VMSTATE_UINT32(apb1smenr2
, Stm32l4x5RccState
),
1353 VMSTATE_UINT32(apb2smenr
, Stm32l4x5RccState
),
1354 VMSTATE_UINT32(ccipr
, Stm32l4x5RccState
),
1355 VMSTATE_UINT32(bdcr
, Stm32l4x5RccState
),
1356 VMSTATE_UINT32(csr
, Stm32l4x5RccState
),
1357 VMSTATE_CLOCK(hsi16_rc
, Stm32l4x5RccState
),
1358 VMSTATE_CLOCK(msi_rc
, Stm32l4x5RccState
),
1359 VMSTATE_CLOCK(hse
, Stm32l4x5RccState
),
1360 VMSTATE_CLOCK(lsi_rc
, Stm32l4x5RccState
),
1361 VMSTATE_CLOCK(lse_crystal
, Stm32l4x5RccState
),
1362 VMSTATE_CLOCK(sai1_extclk
, Stm32l4x5RccState
),
1363 VMSTATE_CLOCK(sai2_extclk
, Stm32l4x5RccState
),
1364 VMSTATE_END_OF_LIST()
1369 static void stm32l4x5_rcc_realize(DeviceState
*dev
, Error
**errp
)
1371 Stm32l4x5RccState
*s
= STM32L4X5_RCC(dev
);
1374 if (s
->hse_frequency
< 4000000ULL ||
1375 s
->hse_frequency
> 48000000ULL) {
1377 "HSE frequency is outside of the allowed [4-48]Mhz range: %" PRIx64
"",
1382 for (i
= 0; i
< RCC_NUM_PLL
; i
++) {
1383 RccPllState
*pll
= &s
->plls
[i
];
1385 clock_set_source(pll
->in
, s
->clock_muxes
[RCC_CLOCK_MUX_PLL_INPUT
].out
);
1387 if (!qdev_realize(DEVICE(pll
), NULL
, errp
)) {
1392 for (i
= 0; i
< RCC_NUM_CLOCK_MUX
; i
++) {
1393 RccClockMuxState
*clock_mux
= &s
->clock_muxes
[i
];
1395 connect_mux_sources(s
, clock_mux
, CLOCK_MUX_INIT_INFO
[i
].src_mapping
);
1397 if (!qdev_realize(DEVICE(clock_mux
), NULL
, errp
)) {
1403 * Start clocks after everything is connected
1404 * to propagate the frequencies along the tree.
1406 clock_update_hz(s
->msi_rc
, MSI_DEFAULT_FRQ
);
1407 clock_update_hz(s
->sai1_extclk
, s
->sai1_extclk_frequency
);
1408 clock_update_hz(s
->sai2_extclk
, s
->sai2_extclk_frequency
);
1409 clock_update(s
->gnd
, 0);
1412 static Property stm32l4x5_rcc_properties
[] = {
1413 DEFINE_PROP_UINT64("hse_frequency", Stm32l4x5RccState
,
1414 hse_frequency
, HSE_DEFAULT_FRQ
),
1415 DEFINE_PROP_UINT64("sai1_extclk_frequency", Stm32l4x5RccState
,
1416 sai1_extclk_frequency
, 0),
1417 DEFINE_PROP_UINT64("sai2_extclk_frequency", Stm32l4x5RccState
,
1418 sai2_extclk_frequency
, 0),
1419 DEFINE_PROP_END_OF_LIST(),
1422 static void stm32l4x5_rcc_class_init(ObjectClass
*klass
, void *data
)
1424 DeviceClass
*dc
= DEVICE_CLASS(klass
);
1425 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
1427 assert(ARRAY_SIZE(CLOCK_MUX_INIT_INFO
) == RCC_NUM_CLOCK_MUX
);
1429 rc
->phases
.hold
= stm32l4x5_rcc_reset_hold
;
1430 device_class_set_props(dc
, stm32l4x5_rcc_properties
);
1431 dc
->realize
= stm32l4x5_rcc_realize
;
1432 dc
->vmsd
= &vmstate_stm32l4x5_rcc
;
1435 static const TypeInfo stm32l4x5_rcc_types
[] = {
1437 .name
= TYPE_STM32L4X5_RCC
,
1438 .parent
= TYPE_SYS_BUS_DEVICE
,
1439 .instance_size
= sizeof(Stm32l4x5RccState
),
1440 .instance_init
= stm32l4x5_rcc_init
,
1441 .class_init
= stm32l4x5_rcc_class_init
,
1443 .name
= TYPE_RCC_CLOCK_MUX
,
1444 .parent
= TYPE_DEVICE
,
1445 .instance_size
= sizeof(RccClockMuxState
),
1446 .instance_init
= clock_mux_init
,
1447 .class_init
= clock_mux_class_init
,
1449 .name
= TYPE_RCC_PLL
,
1450 .parent
= TYPE_DEVICE
,
1451 .instance_size
= sizeof(RccPllState
),
1452 .instance_init
= pll_init
,
1453 .class_init
= pll_class_init
,
1457 DEFINE_TYPES(stm32l4x5_rcc_types
)