 6487653efd
			
		
	
	
		6487653efd
		
	
	
	
	
		
			
			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>
		
			
				
	
	
		
			240 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			240 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * STM32L4X5 RCC (Reset and clock control)
 | |
|  *
 | |
|  * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
 | |
|  * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
 | |
|  *
 | |
|  * SPDX-License-Identifier: GPL-2.0-or-later
 | |
|  *
 | |
|  * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | |
|  * See the COPYING file in the top-level directory.
 | |
|  *
 | |
|  * The reference used is the STMicroElectronics RM0351 Reference manual
 | |
|  * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
 | |
|  *
 | |
|  * Inspired by the BCM2835 CPRMAN clock manager by Luc Michel.
 | |
|  */
 | |
| 
 | |
| #ifndef HW_STM32L4X5_RCC_H
 | |
| #define HW_STM32L4X5_RCC_H
 | |
| 
 | |
| #include "hw/sysbus.h"
 | |
| #include "qom/object.h"
 | |
| 
 | |
| #define TYPE_STM32L4X5_RCC "stm32l4x5-rcc"
 | |
| 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 */
 | |
|     RCC_CLOCK_MUX_SYSCLK,
 | |
|     RCC_CLOCK_MUX_PLL_INPUT,
 | |
|     RCC_CLOCK_MUX_HCLK,
 | |
|     RCC_CLOCK_MUX_PCLK1,
 | |
|     RCC_CLOCK_MUX_PCLK2,
 | |
|     RCC_CLOCK_MUX_HSE_OVER_32,
 | |
|     RCC_CLOCK_MUX_LCD_AND_RTC_COMMON,
 | |
| 
 | |
|     /* Muxes with a publicly available output */
 | |
|     RCC_CLOCK_MUX_CORTEX_REFCLK,
 | |
|     RCC_CLOCK_MUX_USART1,
 | |
|     RCC_CLOCK_MUX_USART2,
 | |
|     RCC_CLOCK_MUX_USART3,
 | |
|     RCC_CLOCK_MUX_UART4,
 | |
|     RCC_CLOCK_MUX_UART5,
 | |
|     RCC_CLOCK_MUX_LPUART1,
 | |
|     RCC_CLOCK_MUX_I2C1,
 | |
|     RCC_CLOCK_MUX_I2C2,
 | |
|     RCC_CLOCK_MUX_I2C3,
 | |
|     RCC_CLOCK_MUX_LPTIM1,
 | |
|     RCC_CLOCK_MUX_LPTIM2,
 | |
|     RCC_CLOCK_MUX_SWPMI1,
 | |
|     RCC_CLOCK_MUX_MCO,
 | |
|     RCC_CLOCK_MUX_LSCO,
 | |
|     RCC_CLOCK_MUX_DFSDM1,
 | |
|     RCC_CLOCK_MUX_ADC,
 | |
|     RCC_CLOCK_MUX_CLK48,
 | |
|     RCC_CLOCK_MUX_SAI1,
 | |
|     RCC_CLOCK_MUX_SAI2,
 | |
| 
 | |
|     /*
 | |
|      * Mux that have only one input and one output assigned to as peripheral.
 | |
|      * They could be direct lines but it is simpler
 | |
|      * to use the same logic for all outputs.
 | |
|      */
 | |
|     /* - AHB1 */
 | |
|     RCC_CLOCK_MUX_TSC,
 | |
|     RCC_CLOCK_MUX_CRC,
 | |
|     RCC_CLOCK_MUX_FLASH,
 | |
|     RCC_CLOCK_MUX_DMA2,
 | |
|     RCC_CLOCK_MUX_DMA1,
 | |
| 
 | |
|     /* - AHB2 */
 | |
|     RCC_CLOCK_MUX_RNG,
 | |
|     RCC_CLOCK_MUX_AES,
 | |
|     RCC_CLOCK_MUX_OTGFS,
 | |
|     RCC_CLOCK_MUX_GPIOA,
 | |
|     RCC_CLOCK_MUX_GPIOB,
 | |
|     RCC_CLOCK_MUX_GPIOC,
 | |
|     RCC_CLOCK_MUX_GPIOD,
 | |
|     RCC_CLOCK_MUX_GPIOE,
 | |
|     RCC_CLOCK_MUX_GPIOF,
 | |
|     RCC_CLOCK_MUX_GPIOG,
 | |
|     RCC_CLOCK_MUX_GPIOH,
 | |
| 
 | |
|     /* - AHB3 */
 | |
|     RCC_CLOCK_MUX_QSPI,
 | |
|     RCC_CLOCK_MUX_FMC,
 | |
| 
 | |
|     /* - APB1 */
 | |
|     RCC_CLOCK_MUX_OPAMP,
 | |
|     RCC_CLOCK_MUX_DAC1,
 | |
|     RCC_CLOCK_MUX_PWR,
 | |
|     RCC_CLOCK_MUX_CAN1,
 | |
|     RCC_CLOCK_MUX_SPI3,
 | |
|     RCC_CLOCK_MUX_SPI2,
 | |
|     RCC_CLOCK_MUX_WWDG,
 | |
|     RCC_CLOCK_MUX_LCD,
 | |
|     RCC_CLOCK_MUX_TIM7,
 | |
|     RCC_CLOCK_MUX_TIM6,
 | |
|     RCC_CLOCK_MUX_TIM5,
 | |
|     RCC_CLOCK_MUX_TIM4,
 | |
|     RCC_CLOCK_MUX_TIM3,
 | |
|     RCC_CLOCK_MUX_TIM2,
 | |
| 
 | |
|     /* - APB2 */
 | |
|     RCC_CLOCK_MUX_TIM17,
 | |
|     RCC_CLOCK_MUX_TIM16,
 | |
|     RCC_CLOCK_MUX_TIM15,
 | |
|     RCC_CLOCK_MUX_TIM8,
 | |
|     RCC_CLOCK_MUX_SPI1,
 | |
|     RCC_CLOCK_MUX_TIM1,
 | |
|     RCC_CLOCK_MUX_SDMMC1,
 | |
|     RCC_CLOCK_MUX_FW,
 | |
|     RCC_CLOCK_MUX_SYSCFG,
 | |
| 
 | |
|     /* - BDCR */
 | |
|     RCC_CLOCK_MUX_RTC,
 | |
| 
 | |
|     /* - OTHER */
 | |
|     RCC_CLOCK_MUX_CORTEX_FCLK,
 | |
| 
 | |
|     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;
 | |
| 
 | |
|     RccClockMux id;
 | |
|     Clock *srcs[RCC_NUM_CLOCK_MUX_SRC];
 | |
|     Clock *out;
 | |
|     bool enabled;
 | |
|     uint32_t src;
 | |
|     uint32_t multiplier;
 | |
|     uint32_t divider;
 | |
| 
 | |
|     /*
 | |
|      * Used by clock srcs update callback to retrieve both the clock and the
 | |
|      * source number.
 | |
|      */
 | |
|     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;
 | |
| 
 | |
|     MemoryRegion mmio;
 | |
| 
 | |
|     uint32_t cr;
 | |
|     uint32_t icscr;
 | |
|     uint32_t cfgr;
 | |
|     uint32_t pllcfgr;
 | |
|     uint32_t pllsai1cfgr;
 | |
|     uint32_t pllsai2cfgr;
 | |
|     uint32_t cier;
 | |
|     uint32_t cifr;
 | |
|     uint32_t ahb1rstr;
 | |
|     uint32_t ahb2rstr;
 | |
|     uint32_t ahb3rstr;
 | |
|     uint32_t apb1rstr1;
 | |
|     uint32_t apb1rstr2;
 | |
|     uint32_t apb2rstr;
 | |
|     uint32_t ahb1enr;
 | |
|     uint32_t ahb2enr;
 | |
|     uint32_t ahb3enr;
 | |
|     uint32_t apb1enr1;
 | |
|     uint32_t apb1enr2;
 | |
|     uint32_t apb2enr;
 | |
|     uint32_t ahb1smenr;
 | |
|     uint32_t ahb2smenr;
 | |
|     uint32_t ahb3smenr;
 | |
|     uint32_t apb1smenr1;
 | |
|     uint32_t apb1smenr2;
 | |
|     uint32_t apb2smenr;
 | |
|     uint32_t ccipr;
 | |
|     uint32_t bdcr;
 | |
|     uint32_t csr;
 | |
| 
 | |
|     /* Clock sources */
 | |
|     Clock *gnd;
 | |
|     Clock *hsi16_rc;
 | |
|     Clock *msi_rc;
 | |
|     Clock *hse;
 | |
|     Clock *lsi_rc;
 | |
|     Clock *lse_crystal;
 | |
|     Clock *sai1_extclk;
 | |
|     Clock *sai2_extclk;
 | |
| 
 | |
|     /* PLLs */
 | |
|     RccPllState plls[RCC_NUM_PLL];
 | |
| 
 | |
|     /* Muxes ~= outputs */
 | |
|     RccClockMuxState clock_muxes[RCC_NUM_CLOCK_MUX];
 | |
| 
 | |
|     qemu_irq irq;
 | |
|     uint64_t hse_frequency;
 | |
|     uint64_t sai1_extclk_frequency;
 | |
|     uint64_t sai2_extclk_frequency;
 | |
| };
 | |
| 
 | |
| #endif /* HW_STM32L4X5_RCC_H */
 |