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>
This commit is contained in:
Arnaud Minier 2024-03-03 15:06:38 +01:00 committed by Peter Maydell
parent ec7d83acbd
commit 6487653efd
4 changed files with 243 additions and 0 deletions

View file

@ -26,6 +26,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5RccState, STM32L4X5_RCC)
/* 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 @@ typedef enum RccClockMux {
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 @@ typedef struct RccClockMuxState {
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 @@ struct Stm32l4x5RccState {
Clock *sai1_extclk;
Clock *sai2_extclk;
/* PLLs */
RccPllState plls[RCC_NUM_PLL];
/* Muxes ~= outputs */
RccClockMuxState clock_muxes[RCC_NUM_CLOCK_MUX];

View file

@ -22,7 +22,10 @@
#include "hw/misc/stm32l4x5_rcc.h"
#define TYPE_RCC_CLOCK_MUX "stm32l4x5-rcc-clock-mux"
#define TYPE_RCC_PLL "stm32l4x5-rcc-pll"
OBJECT_DECLARE_SIMPLE_TYPE(RccClockMuxState, RCC_CLOCK_MUX)
OBJECT_DECLARE_SIMPLE_TYPE(RccPllState, RCC_PLL)
/* Register map */
REG32(CR, 0x00)
@ -285,6 +288,25 @@ REG32(CSR, 0x94)
R_CSR_FWRSTF_MASK | \
R_CSR_LSIRDY_MASK)
/* Pll Channels */
enum PllChannels {
RCC_PLL_CHANNEL_PLLSAI3CLK = 0,
RCC_PLL_CHANNEL_PLL48M1CLK = 1,
RCC_PLL_CHANNEL_PLLCLK = 2,
};
enum PllSai1Channels {
RCC_PLLSAI1_CHANNEL_PLLSAI1CLK = 0,
RCC_PLLSAI1_CHANNEL_PLL48M2CLK = 1,
RCC_PLLSAI1_CHANNEL_PLLADC1CLK = 2,
};
enum PllSai2Channels {
RCC_PLLSAI2_CHANNEL_PLLSAI2CLK = 0,
/* No Q channel */
RCC_PLLSAI2_CHANNEL_PLLADC2CLK = 2,
};
typedef enum RccClockMuxSource {
RCC_CLOCK_MUX_SRC_GND = 0,
RCC_CLOCK_MUX_SRC_HSI,