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 */
|