hw/misc/stm32l4x5_rcc: Add an internal PLL Clock object

This object represents the PLLs and their channels. The PLLs allow for a
more fine-grained control of the clocks frequency.

The migration handling is based on hw/misc/zynq_sclr.c.
Three phase reset will be handled in a later commit.

Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
Message-id: 20240303140643.81957-4-arnaud.minier@telecom-paris.fr
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/include/hw/misc/stm32l4x5_rcc.h b/include/hw/misc/stm32l4x5_rcc.h
index 6719be9..0fbfba5 100644
--- a/include/hw/misc/stm32l4x5_rcc.h
+++ b/include/hw/misc/stm32l4x5_rcc.h
@@ -26,6 +26,15 @@
 
 /* In the Stm32l4x5 clock tree, mux have at most 7 sources */
 #define RCC_NUM_CLOCK_MUX_SRC 7
+
+typedef enum PllCommonChannels {
+    RCC_PLL_COMMON_CHANNEL_P = 0,
+    RCC_PLL_COMMON_CHANNEL_Q = 1,
+    RCC_PLL_COMMON_CHANNEL_R = 2,
+
+    RCC_NUM_CHANNEL_PLL_OUT = 3
+} PllCommonChannels;
+
 /* NB: Prescaler are assimilated to mux with one source and one output */
 typedef enum RccClockMux {
     /* Internal muxes that arent't exposed publicly to other peripherals */
@@ -124,6 +133,14 @@
     RCC_NUM_CLOCK_MUX
 } RccClockMux;
 
+typedef enum RccPll {
+    RCC_PLL_PLL,
+    RCC_PLL_PLLSAI1,
+    RCC_PLL_PLLSAI2,
+
+    RCC_NUM_PLL
+} RccPll;
+
 typedef struct RccClockMuxState {
     DeviceState parent_obj;
 
@@ -142,6 +159,26 @@
     struct RccClockMuxState *backref[RCC_NUM_CLOCK_MUX_SRC];
 } RccClockMuxState;
 
+typedef struct RccPllState {
+    DeviceState parent_obj;
+
+    RccPll id;
+    Clock *in;
+    uint32_t vco_multiplier;
+    Clock *channels[RCC_NUM_CHANNEL_PLL_OUT];
+    /* Global pll enabled flag */
+    bool enabled;
+    /* 'enabled' refers to the runtime configuration */
+    bool channel_enabled[RCC_NUM_CHANNEL_PLL_OUT];
+    /*
+     * 'exists' refers to the physical configuration
+     * It should only be set at pll initialization.
+     * e.g. pllsai2 doesn't have a Q output.
+     */
+    bool channel_exists[RCC_NUM_CHANNEL_PLL_OUT];
+    uint32_t channel_divider[RCC_NUM_CHANNEL_PLL_OUT];
+} RccPllState;
+
 struct Stm32l4x5RccState {
     SysBusDevice parent_obj;
 
@@ -187,6 +224,9 @@
     Clock *sai1_extclk;
     Clock *sai2_extclk;
 
+    /* PLLs */
+    RccPllState plls[RCC_NUM_PLL];
+
     /* Muxes ~= outputs */
     RccClockMuxState clock_muxes[RCC_NUM_CLOCK_MUX];