[PATCH] clk: stm32mp13: Add SPL support and clock tree init to STM32MP13 RCC driver
Marek Vasut
marek.vasut at mailbox.org
Mon May 12 19:08:29 CEST 2025
Add SPL support and clock tree init to STM32MP13 RCC driver. This
consists of two parts, make SCMI into an optional dependency and
add clock tree initialization. The SCMI dependency is made optional
first by registering the few core clock provided by SCMI clock as
fixed clock, and second by letting the clock core parse out the
clock configuration from SoC registers. The clock initialization
code is derived from STM32MP15xx clock tree initialization code,
which is almost identical, except for the use of new PLL2000 for
PLL1 on STM32MP13xx .
Signed-off-by: Marek Vasut <marek.vasut at mailbox.org>
---
Cc: Patrice Chotard <patrice.chotard at foss.st.com>
Cc: Patrick Delaunay <patrick.delaunay at foss.st.com>
Cc: Sean Anderson <seanga2 at gmail.com>
Cc: Tom Rini <trini at konsulko.com>
Cc: u-boot at lists.denx.de
Cc: uboot-stm32 at st-md-mailman.stormreply.com
---
drivers/clk/stm32/clk-stm32-core.h | 1 +
drivers/clk/stm32/clk-stm32mp13.c | 1303 +++++++++++++++++-
drivers/clk/stm32/stm32mp13_rcc.h | 93 ++
include/dt-bindings/clock/stm32mp13-clksrc.h | 399 ++++++
4 files changed, 1744 insertions(+), 52 deletions(-)
create mode 100644 include/dt-bindings/clock/stm32mp13-clksrc.h
diff --git a/drivers/clk/stm32/clk-stm32-core.h b/drivers/clk/stm32/clk-stm32-core.h
index f9ef0702005..123643b03a6 100644
--- a/drivers/clk/stm32/clk-stm32-core.h
+++ b/drivers/clk/stm32/clk-stm32-core.h
@@ -144,6 +144,7 @@ struct stm32mp_rcc_priv {
void __iomem *base;
u8 *gate_cpt;
const struct clk_stm32_clock_data *data;
+ struct clk osc_clk[6];
};
int stm32_rcc_init(struct udevice *dev,
diff --git a/drivers/clk/stm32/clk-stm32mp13.c b/drivers/clk/stm32/clk-stm32mp13.c
index 11dc40383a4..fabef4dbd3f 100644
--- a/drivers/clk/stm32/clk-stm32mp13.c
+++ b/drivers/clk/stm32/clk-stm32mp13.c
@@ -3,7 +3,6 @@
* Copyright (C) 2022, STMicroelectronics - All Rights Reserved
* Author: Gabriel Fernandez <gabriel.fernandez at foss.st.com> for STMicroelectronics.
*/
-
#define LOG_CATEGORY UCLASS_CLK
#include <clk-uclass.h>
@@ -12,6 +11,22 @@
#include <asm/io.h>
#include <dt-bindings/clock/stm32mp13-clks.h>
#include <linux/clk-provider.h>
+#include <dt-bindings/clock/stm32mp13-clksrc.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/global_data.h>
+#include <clk-uclass.h>
+#include <div64.h>
+#include <dm/device_compat.h>
+#include <init.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <regmap.h>
+#include <spl.h>
+#include <syscon.h>
+#include <time.h>
+#include <vsprintf.h>
+#include <asm/arch/sys_proto.h>
#include "clk-stm32-core.h"
#include "stm32mp13_rcc.h"
@@ -130,46 +145,6 @@ static const char * const usbphy_src[] = {
"ck_hse", "pll4_r", "clk-hse-div2"
};
-enum enum_mux_cfg {
- MUX_I2C12,
- MUX_LPTIM45,
- MUX_SPI23,
- MUX_UART35,
- MUX_UART78,
- MUX_ADC1,
- MUX_ADC2,
- MUX_DCMIPP,
- MUX_ETH1,
- MUX_ETH2,
- MUX_FDCAN,
- MUX_FMC,
- MUX_I2C3,
- MUX_I2C4,
- MUX_I2C5,
- MUX_LPTIM1,
- MUX_LPTIM2,
- MUX_LPTIM3,
- MUX_QSPI,
- MUX_RNG1,
- MUX_SAES,
- MUX_SAI1,
- MUX_SAI2,
- MUX_SDMMC1,
- MUX_SDMMC2,
- MUX_SPDIF,
- MUX_SPI1,
- MUX_SPI4,
- MUX_SPI5,
- MUX_STGEN,
- MUX_UART1,
- MUX_UART2,
- MUX_UART4,
- MUX_UART6,
- MUX_USBO,
- MUX_USBPHY,
- MUX_MCO1,
- MUX_MCO2
-};
#define MUX_CFG(id, src, _offset, _shift, _witdh) \
[id] = { \
@@ -471,15 +446,6 @@ static const struct clk_div_table ck_trace_div_table[] = {
{ 0 },
};
-enum enum_div_cfg {
- DIV_MCO1,
- DIV_MCO2,
- DIV_TRACE,
- DIV_ETH1PTP,
- DIV_ETH2PTP,
- LAST_DIV
-};
-
#define DIV_CFG(id, _offset, _shift, _width, _flags, _table) \
[id] = { \
.reg_off = _offset, \
@@ -489,7 +455,7 @@ enum enum_div_cfg {
.table = _table, \
}
-static const struct stm32_div_cfg stm32mp13_dividers[LAST_DIV] = {
+static const struct stm32_div_cfg stm32mp13_dividers[] = {
DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL),
DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL),
DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table),
@@ -566,6 +532,7 @@ enum securit_clk {
.bit_idx = _bit_idx, \
}
+#ifdef CONFIG_TFABOOT
static const struct clk_stm32_security stm32mp13_security[] = {
SECF(SECF_LPTIM2, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM2SECF),
SECF(SECF_LPTIM3, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM3SECF),
@@ -622,6 +589,7 @@ static const struct clk_stm32_security stm32mp13_security[] = {
SECF(SECF_MCO1, RCC_SECCFGR, RCC_SECCFGR_MCO1SECF),
SECF(SECF_MCO2, RCC_SECCFGR, RCC_SECCFGR_MCO2SECF),
};
+#endif
#define PCLK(_id, _name, _parent, _flags, _gate_id, _sec_id) \
STM32_GATE(_id, _name, _parent, _flags, _gate_id, _sec_id)
@@ -635,6 +603,7 @@ static const struct clk_stm32_security stm32mp13_security[] = {
_gate_id, _mux_id, NO_STM32_DIV)
static const struct clock_config stm32mp13_clock_cfg[] = {
+#ifndef CONFIG_XPL_BUILD
TIMER(TIM2_K, "tim2_k", "timg1_ck", 0, GATE_TIM2, SECF_NONE),
TIMER(TIM3_K, "tim3_k", "timg1_ck", 0, GATE_TIM3, SECF_NONE),
TIMER(TIM4_K, "tim4_k", "timg1_ck", 0, GATE_TIM4, SECF_NONE),
@@ -649,23 +618,28 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
TIMER(TIM15_K, "tim15_k", "timg3_ck", 0, GATE_TIM15, SECF_TIM15),
TIMER(TIM16_K, "tim16_k", "timg3_ck", 0, GATE_TIM16, SECF_TIM16),
TIMER(TIM17_K, "tim17_k", "timg3_ck", 0, GATE_TIM17, SECF_TIM17),
+#endif
/* Peripheral clocks */
PCLK(SYSCFG, "syscfg", "pclk3", 0, GATE_SYSCFG, SECF_NONE),
PCLK(VREF, "vref", "pclk3", 0, GATE_VREF, SECF_VREF),
+#ifndef CONFIG_XPL_BUILD
PCLK(PMBCTRL, "pmbctrl", "pclk3", 0, GATE_PMBCTRL, SECF_NONE),
PCLK(HDP, "hdp", "pclk3", 0, GATE_HDP, SECF_NONE),
+#endif
PCLK(IWDG2, "iwdg2", "pclk4", 0, GATE_IWDG2APB, SECF_NONE),
PCLK(STGENRO, "stgenro", "pclk4", 0, GATE_STGENRO, SECF_STGENRO),
PCLK(TZPC, "tzpc", "pclk5", 0, GATE_TZC, SECF_TZC),
PCLK(IWDG1, "iwdg1", "pclk5", 0, GATE_IWDG1APB, SECF_IWDG1),
PCLK(BSEC, "bsec", "pclk5", 0, GATE_BSEC, SECF_BSEC),
+#ifndef CONFIG_XPL_BUILD
PCLK(DMA1, "dma1", "ck_mlahb", 0, GATE_DMA1, SECF_NONE),
PCLK(DMA2, "dma2", "ck_mlahb", 0, GATE_DMA2, SECF_NONE),
PCLK(DMAMUX1, "dmamux1", "ck_mlahb", 0, GATE_DMAMUX1, SECF_NONE),
PCLK(DMAMUX2, "dmamux2", "ck_mlahb", 0, GATE_DMAMUX2, SECF_DMAMUX2),
PCLK(ADC1, "adc1", "ck_mlahb", 0, GATE_ADC1, SECF_ADC1),
PCLK(ADC2, "adc2", "ck_mlahb", 0, GATE_ADC2, SECF_ADC2),
+#endif
PCLK(GPIOA, "gpioa", "pclk4", 0, GATE_GPIOA, SECF_NONE),
PCLK(GPIOB, "gpiob", "pclk4", 0, GATE_GPIOB, SECF_NONE),
PCLK(GPIOC, "gpioc", "pclk4", 0, GATE_GPIOC, SECF_NONE),
@@ -681,17 +655,23 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
PCLK(HASH1, "hash1", "ck_axi", 0, GATE_HASH1, SECF_HASH1),
PCLK(BKPSRAM, "bkpsram", "ck_axi", 0, GATE_BKPSRAM, SECF_BKPSRAM),
PCLK(MDMA, "mdma", "ck_axi", 0, GATE_MDMA, SECF_NONE),
+#ifndef CONFIG_XPL_BUILD
PCLK(ETH1TX, "eth1tx", "ck_axi", 0, GATE_ETH1TX, SECF_ETH1TX),
PCLK(ETH1RX, "eth1rx", "ck_axi", 0, GATE_ETH1RX, SECF_ETH1RX),
PCLK(ETH1MAC, "eth1mac", "ck_axi", 0, GATE_ETH1MAC, SECF_ETH1MAC),
PCLK(ETH2TX, "eth2tx", "ck_axi", 0, GATE_ETH2TX, SECF_ETH2TX),
PCLK(ETH2RX, "eth2rx", "ck_axi", 0, GATE_ETH2RX, SECF_ETH2RX),
PCLK(ETH2MAC, "eth2mac", "ck_axi", 0, GATE_ETH2MAC, SECF_ETH2MAC),
+#endif
PCLK(CRC1, "crc1", "ck_axi", 0, GATE_CRC1, SECF_NONE),
+#ifndef CONFIG_XPL_BUILD
PCLK(USBH, "usbh", "ck_axi", 0, GATE_USBH, SECF_NONE),
+#endif
PCLK(DDRPERFM, "ddrperfm", "pclk4", 0, GATE_DDRPERFM, SECF_NONE),
+#ifndef CONFIG_XPL_BUILD
PCLK(ETH1STP, "eth1stp", "ck_axi", 0, GATE_ETH1STP, SECF_ETH1STP),
PCLK(ETH2STP, "eth2stp", "ck_axi", 0, GATE_ETH2STP, SECF_ETH2STP),
+#endif
/* Kernel clocks */
KCLK(SDMMC1_K, "sdmmc1_k", 0, GATE_SDMMC1, MUX_SDMMC1, SECF_SDMMC1),
@@ -702,8 +682,10 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
KCLK(SPI3_K, "spi3_k", 0, GATE_SPI3, MUX_SPI23, SECF_NONE),
KCLK(I2C1_K, "i2c1_k", 0, GATE_I2C1, MUX_I2C12, SECF_NONE),
KCLK(I2C2_K, "i2c2_k", 0, GATE_I2C2, MUX_I2C12, SECF_NONE),
+#ifndef CONFIG_XPL_BUILD
KCLK(LPTIM4_K, "lptim4_k", 0, GATE_LPTIM4, MUX_LPTIM45, SECF_NONE),
KCLK(LPTIM5_K, "lptim5_k", 0, GATE_LPTIM5, MUX_LPTIM45, SECF_NONE),
+#endif
KCLK(USART3_K, "usart3_k", 0, GATE_USART3, MUX_UART35, SECF_NONE),
KCLK(UART5_K, "uart5_k", 0, GATE_UART5, MUX_UART35, SECF_NONE),
KCLK(UART7_K, "uart7_k", 0, GATE_UART7, MUX_UART78, SECF_NONE),
@@ -711,20 +693,29 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
KCLK(RNG1_K, "rng1_k", 0, GATE_RNG1, MUX_RNG1, SECF_RNG1),
KCLK(USBPHY_K, "usbphy_k", 0, GATE_USBPHY, MUX_USBPHY, SECF_USBPHY),
KCLK(STGEN_K, "stgen_k", 0, GATE_STGENC, MUX_STGEN, SECF_STGENC),
+#ifndef CONFIG_XPL_BUILD
KCLK(SPDIF_K, "spdif_k", 0, GATE_SPDIF, MUX_SPDIF, SECF_NONE),
+#endif
KCLK(SPI1_K, "spi1_k", 0, GATE_SPI1, MUX_SPI1, SECF_NONE),
KCLK(SPI4_K, "spi4_k", 0, GATE_SPI4, MUX_SPI4, SECF_SPI4),
KCLK(SPI5_K, "spi5_k", 0, GATE_SPI5, MUX_SPI5, SECF_SPI5),
+#ifdef CONFIG_TFABOOT
KCLK(I2C3_K, "i2c3_k", 0, GATE_I2C3, MUX_I2C3, SECF_I2C3),
+#else
+ KCLK(I2C3_K, "i2c3_k", 0, GATE_I2C3, MUX_I2C3, SECF_NONE),
+#endif
KCLK(I2C4_K, "i2c4_k", 0, GATE_I2C4, MUX_I2C4, SECF_I2C4),
KCLK(I2C5_K, "i2c5_k", 0, GATE_I2C5, MUX_I2C5, SECF_I2C5),
+#ifndef CONFIG_XPL_BUILD
KCLK(LPTIM1_K, "lptim1_k", 0, GATE_LPTIM1, MUX_LPTIM1, SECF_NONE),
KCLK(LPTIM2_K, "lptim2_k", 0, GATE_LPTIM2, MUX_LPTIM2, SECF_LPTIM2),
KCLK(LPTIM3_K, "lptim3_k", 0, GATE_LPTIM3, MUX_LPTIM3, SECF_LPTIM3),
+#endif
KCLK(USART1_K, "usart1_k", 0, GATE_USART1, MUX_UART1, SECF_USART1),
KCLK(USART2_K, "usart2_k", 0, GATE_USART2, MUX_UART2, SECF_USART2),
KCLK(UART4_K, "uart4_k", 0, GATE_UART4, MUX_UART4, SECF_NONE),
KCLK(USART6_K, "uart6_k", 0, GATE_USART6, MUX_UART6, SECF_NONE),
+#ifndef CONFIG_XPL_BUILD
KCLK(FDCAN_K, "fdcan_k", 0, GATE_FDCAN, MUX_FDCAN, SECF_NONE),
KCLK(SAI1_K, "sai1_k", 0, GATE_SAI1, MUX_SAI1, SECF_NONE),
KCLK(SAI2_K, "sai2_k", 0, GATE_SAI2, MUX_SAI2, SECF_NONE),
@@ -732,7 +723,9 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
KCLK(ADC2_K, "adc2_k", 0, GATE_ADC2, MUX_ADC2, SECF_ADC2),
KCLK(DCMIPP_K, "dcmipp_k", 0, GATE_DCMIPP, MUX_DCMIPP, SECF_DCMIPP),
KCLK(ADFSDM_K, "adfsdm_k", 0, GATE_ADFSDM, MUX_SAI1, SECF_NONE),
+#endif
KCLK(USBO_K, "usbo_k", 0, GATE_USBO, MUX_USBO, SECF_USBO),
+#ifndef CONFIG_XPL_BUILD
KCLK(ETH1CK_K, "eth1ck_k", 0, GATE_ETH1CK, MUX_ETH1, SECF_ETH1CK),
KCLK(ETH2CK_K, "eth2ck_k", 0, GATE_ETH2CK, MUX_ETH2, SECF_ETH2CK),
KCLK(SAES_K, "saes_k", 0, GATE_SAES, MUX_SAES, SECF_SAES),
@@ -742,6 +735,7 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
GATE_LTDC, SECF_NONE),
STM32_GATE(DTS_K, "dts_k", "ck_lse", 0, GATE_DTS, SECF_NONE),
+#endif
STM32_COMPOSITE(ETH1PTP_K, "eth1ptp_k", CLK_OPS_PARENT_ENABLE |
CLK_SET_RATE_NO_REPARENT, SECF_ETH1CK,
@@ -767,8 +761,22 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
STM32_COMPOSITE_NOMUX(CK_TRACE, "ck_trace", "ck_axi",
CLK_OPS_PARENT_ENABLE, SECF_NONE,
GATE_TRACECK, DIV_TRACE),
+
+#ifdef CONFIG_XPL_BUILD
+ STM32_GATE(AXIDCG, "axidcg", "ck_axi", CLK_IGNORE_UNUSED,
+ GATE_AXIDCG, SECF_NONE),
+ STM32_GATE(DDRC1, "ddrc1", "ck_axi", CLK_IGNORE_UNUSED,
+ GATE_DDRC1, SECF_NONE),
+ STM32_GATE(DDRPHYC, "ddrphyc", "pll2_r", CLK_IGNORE_UNUSED,
+ GATE_DDRPHYC, SECF_NONE),
+ STM32_GATE(DDRCAPB, "ddrcapb", "pclk4", CLK_IGNORE_UNUSED,
+ GATE_DDRCAPB, SECF_NONE),
+ STM32_GATE(DDRPHYCAPB, "ddrphycapb", "pclk4", CLK_IGNORE_UNUSED,
+ GATE_DDRPHYCAPB, SECF_NONE),
+#endif
};
+#ifdef CONFIG_TFABOOT
static int stm32mp13_check_security(void __iomem *base,
const struct clock_config *cfg)
{
@@ -784,6 +792,7 @@ static int stm32mp13_check_security(void __iomem *base,
return secured;
}
+#endif
static const struct stm32_clock_match_data stm32mp13_data = {
.tab_clocks = stm32mp13_clock_cfg,
@@ -794,16 +803,1204 @@ static const struct stm32_clock_match_data stm32mp13_data = {
.muxes = stm32mp13_muxes,
.dividers = stm32mp13_dividers,
},
+#ifdef CONFIG_TFABOOT
.check_security = stm32mp13_check_security,
+#endif
+};
+
+#ifndef CONFIG_TFABOOT
+
+enum stm32mp1_parent_id {
+/*
+ * _HSI, _HSE, _CSI, _LSI, _LSE should not be moved
+ * they are used as index in osc_clk[] as clock reference
+ */
+ _HSI,
+ _HSE,
+ _CSI,
+ _LSI,
+ _LSE,
+ _I2S_CKIN,
+ NB_OSC,
+
+/* other parent source */
+ _HSI_KER = NB_OSC,
+ _HSE_KER,
+ _HSE_KER_DIV2,
+ _CSI_KER,
+ _PLL1_P,
+ _PLL1_Q,
+ _PLL1_R,
+ _PLL2_P,
+ _PLL2_Q,
+ _PLL2_R,
+ _PLL3_P,
+ _PLL3_Q,
+ _PLL3_R,
+ _PLL4_P,
+ _PLL4_Q,
+ _PLL4_R,
+ _ACLK,
+ _PCLK1,
+ _PCLK2,
+ _PCLK3,
+ _PCLK4,
+ _PCLK5,
+ _HCLK6,
+ _HCLK2,
+ _CK_PER,
+ _CK_MPU,
+ _CK_MCU,
+ _DSI_PHY,
+ _USB_PHY_48,
+ _PARENT_NB,
+ _UNKNOWN_ID = 0xff,
+};
+
+#if defined(CONFIG_XPL_BUILD)
+
+#define MAX_HSI_HZ 64000000
+
+/* TIMEOUT */
+#define TIMEOUT_200MS 200000
+#define TIMEOUT_1S 1000000
+
+/* STGEN registers */
+#define STGENC_CNTCR 0x00
+#define STGENC_CNTSR 0x04
+#define STGENC_CNTCVL 0x08
+#define STGENC_CNTCVU 0x0C
+#define STGENC_CNTFID0 0x20
+
+#define STGENC_CNTCR_EN BIT(0)
+
+enum stm32mp1_clksrc_id {
+ CLKSRC_MPU,
+ CLKSRC_AXI,
+ CLKSRC_MLAHB,
+ CLKSRC_PLL12,
+ CLKSRC_PLL3,
+ CLKSRC_PLL4,
+ CLKSRC_RTC,
+ CLKSRC_MCO1,
+ CLKSRC_MCO2,
+ CLKSRC_NB
+};
+
+enum stm32mp1_clkdiv_id {
+ CLKDIV_AXI,
+ CLKDIV_MLAHB,
+ CLKDIV_APB1,
+ CLKDIV_APB2,
+ CLKDIV_APB3,
+ CLKDIV_APB4,
+ CLKDIV_APB5,
+ CLKDIV_APB6,
+ CLKDIV_RTC,
+ CLKDIV_NB
+};
+
+enum stm32mp1_pll_id {
+ _PLL1,
+ _PLL2,
+ _PLL3,
+ _PLL4,
+ _PLL_NB
+};
+
+enum stm32mp1_div_id {
+ _DIV_P,
+ _DIV_Q,
+ _DIV_R,
+ _DIV_NB,
+};
+
+/* define characteristic of PLL according type */
+#define DIVM_MIN 1
+#define DIVM_MAX 63
+#define DIVN_MIN 24
+#define DIVP_MIN 0
+#define DIVP_MAX 127
+#define FRAC_MAX 8192
+
+#define PLL2000_VCO_MIN 992000000
+#define PLL2000_VCO_MAX 2000000000
+
+enum stm32mp1_pllcfg {
+ PLLCFG_M,
+ PLLCFG_N,
+ PLLCFG_P,
+ PLLCFG_Q,
+ PLLCFG_R,
+ PLLCFG_O,
+ PLLCFG_NB
+};
+
+enum stm32mp1_pllcsg {
+ PLLCSG_MOD_PER,
+ PLLCSG_INC_STEP,
+ PLLCSG_SSCG_MODE,
+ PLLCSG_NB
+};
+
+enum stm32mp1_plltype {
+ PLL_800,
+ PLL_1600,
+ PLL_2000,
+ PLL_TYPE_NB
+};
+
+struct stm32mp1_pll {
+ u8 refclk_min;
+ u8 refclk_max;
+ u8 divn_max;
+};
+
+#define REFCLK_SIZE 4
+struct stm32mp1_clk_pll {
+ enum stm32mp1_plltype plltype;
+ u16 rckxselr;
+ u16 pllxcfgr1;
+ u16 pllxcfgr2;
+ u16 pllxfracr;
+ u16 pllxcr;
+ u16 pllxcsgr;
+ u8 refclk[REFCLK_SIZE];
+};
+
+static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
+ [PLL_800] = {
+ .refclk_min = 4,
+ .refclk_max = 16,
+ .divn_max = 99,
+ },
+ [PLL_1600] = {
+ .refclk_min = 8,
+ .refclk_max = 16,
+ .divn_max = 199,
+ },
+ [PLL_2000] = {
+ .refclk_min = 8,
+ .refclk_max = 16,
+ .divn_max = 99,
+ },
+};
+
+#define STM32MP1_CLK_PLL(idx, type, off1, off2, off3, off4, off5, off6,\
+ p1, p2, p3, p4) \
+ [(idx)] = { \
+ .plltype = (type), \
+ .rckxselr = (off1), \
+ .pllxcfgr1 = (off2), \
+ .pllxcfgr2 = (off3), \
+ .pllxfracr = (off4), \
+ .pllxcr = (off5), \
+ .pllxcsgr = (off6), \
+ .refclk[0] = (p1), \
+ .refclk[1] = (p2), \
+ .refclk[2] = (p3), \
+ .refclk[3] = (p4), \
+ }
+
+static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
+ STM32MP1_CLK_PLL(_PLL1, PLL_2000,
+ RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
+ RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
+ _HSI, _HSE, _UNKNOWN_ID, _UNKNOWN_ID),
+ STM32MP1_CLK_PLL(_PLL2, PLL_1600,
+ RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
+ RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
+ _HSI, _HSE, _UNKNOWN_ID, _UNKNOWN_ID),
+ STM32MP1_CLK_PLL(_PLL3, PLL_800,
+ RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
+ RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
+ _HSI, _HSE, _CSI, _UNKNOWN_ID),
+ STM32MP1_CLK_PLL(_PLL4, PLL_800,
+ RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
+ RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
+ _HSI, _HSE, _CSI, _I2S_CKIN),
};
+static ulong stm32mp1_clk_get_fixed(struct stm32mp_rcc_priv *priv, int idx)
+{
+ if (idx >= NB_OSC) {
+ log_debug("clk id %d not found\n", idx);
+ return 0;
+ }
+
+ return clk_get_rate(&priv->osc_clk[idx]);
+}
+
+bool stm32mp1_supports_opp(u32 opp_id, u32 cpu_type)
+{
+ /* 650 MHz is always supported */
+ if (opp_id == 1)
+ return true;
+
+ /*
+ * 1000 MHz is supported on STM32MP13xDxx and STM32MP13xFxx,
+ * which all have bit 11 i.e. 0x800 set in CPU ID.
+ */
+ if (opp_id == 2)
+ return !!(cpu_type & BIT(11));
+
+ /* Any other OPP is invalid. */
+ return false;
+}
+
+__weak void board_vddcore_init(u32 voltage_mv)
+{
+}
+
+/*
+ * gets OPP parameters (frequency in KHz and voltage in mV) from
+ * an OPP table subnode. Platform HW support capabilities are also checked.
+ * Returns 0 on success and a negative FDT error code on failure.
+ */
+static int stm32mp1_get_opp(u32 cpu_type, ofnode subnode,
+ u32 *freq_khz, u32 *voltage_mv)
+{
+ u32 opp_hw;
+ u64 read_freq_64;
+ u32 read_voltage_32;
+
+ *freq_khz = 0;
+ *voltage_mv = 0;
+
+ opp_hw = ofnode_read_u32_default(subnode, "opp-supported-hw", 0);
+ if (opp_hw)
+ if (!stm32mp1_supports_opp(opp_hw, cpu_type))
+ return -FDT_ERR_BADVALUE;
+
+ read_freq_64 = ofnode_read_u64_default(subnode, "opp-hz", 0) /
+ 1000ULL;
+ read_voltage_32 = ofnode_read_u32_default(subnode, "opp-microvolt", 0) /
+ 1000U;
+
+ if (!read_voltage_32 || !read_freq_64)
+ return -FDT_ERR_NOTFOUND;
+
+ /* Frequency value expressed in KHz must fit on 32 bits */
+ if (read_freq_64 > U32_MAX)
+ return -FDT_ERR_BADVALUE;
+
+ /* Millivolt value must fit on 16 bits */
+ if (read_voltage_32 > U16_MAX)
+ return -FDT_ERR_BADVALUE;
+
+ *freq_khz = (u32)read_freq_64;
+ *voltage_mv = read_voltage_32;
+
+ return 0;
+}
+
+/*
+ * parses OPP table in DT and finds the parameters for the
+ * highest frequency supported by the HW platform.
+ * Returns 0 on success and a negative FDT error code on failure.
+ */
+int stm32mp1_get_max_opp_freq(struct stm32mp_rcc_priv *priv, u64 *freq_hz)
+{
+ ofnode node, subnode;
+ int ret;
+ u32 freq = 0U, voltage = 0U;
+ u32 cpu_type = get_cpu_type();
+
+ node = ofnode_by_compatible(ofnode_null(), "operating-points-v2");
+ if (!ofnode_valid(node))
+ return -FDT_ERR_NOTFOUND;
+
+ ofnode_for_each_subnode(subnode, node) {
+ unsigned int read_freq;
+ unsigned int read_voltage;
+
+ ret = stm32mp1_get_opp(cpu_type, subnode,
+ &read_freq, &read_voltage);
+ if (ret)
+ continue;
+
+ if (read_freq > freq) {
+ freq = read_freq;
+ voltage = read_voltage;
+ }
+ }
+
+ if (!freq || !voltage)
+ return -FDT_ERR_NOTFOUND;
+
+ *freq_hz = (u64)1000U * freq;
+ board_vddcore_init(voltage);
+
+ return 0;
+}
+
+static int stm32mp1_pll1_opp(struct stm32mp_rcc_priv *priv, int clksrc,
+ u32 *pllcfg, u32 *fracv)
+{
+ u32 post_divm;
+ u32 input_freq;
+ u64 output_freq;
+ u64 freq;
+ u64 vco;
+ u32 divm, divn, divp, frac;
+ int i, ret;
+ u32 diff;
+ u32 best_diff = U32_MAX;
+
+ /* PLL1 is 2000 */
+ const u32 DIVN_MAX = stm32mp1_pll[PLL_2000].divn_max;
+ const u32 POST_DIVM_MIN = stm32mp1_pll[PLL_2000].refclk_min * 1000000U;
+ const u32 POST_DIVM_MAX = stm32mp1_pll[PLL_2000].refclk_max * 1000000U;
+
+ ret = stm32mp1_get_max_opp_freq(priv, &output_freq);
+ if (ret) {
+ log_debug("PLL1 OPP configuration not found (%d).\n", ret);
+ return ret;
+ }
+
+ switch (clksrc) {
+ case CLK_PLL12_HSI:
+ input_freq = stm32mp1_clk_get_fixed(priv, _HSI);
+ break;
+ case CLK_PLL12_HSE:
+ input_freq = stm32mp1_clk_get_fixed(priv, _HSE);
+ break;
+ default:
+ return -EINTR;
+ }
+
+ /* Following parameters have always the same value */
+ pllcfg[PLLCFG_Q] = 0;
+ pllcfg[PLLCFG_R] = 0;
+ pllcfg[PLLCFG_O] = PQR(1, 1, 1);
+
+ for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) {
+ post_divm = (u32)(input_freq / (divm + 1));
+ if (post_divm < POST_DIVM_MIN || post_divm > POST_DIVM_MAX)
+ continue;
+
+ for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) {
+ freq = output_freq * (divm + 1) * (divp + 1);
+ divn = (u32)((freq / input_freq) - 1);
+ if (divn < DIVN_MIN || divn > DIVN_MAX)
+ continue;
+
+ frac = (u32)(((freq * FRAC_MAX) / input_freq) -
+ ((divn + 1) * FRAC_MAX));
+ /* 2 loops to refine the fractional part */
+ for (i = 2; i != 0; i--) {
+ if (frac > FRAC_MAX)
+ break;
+
+ vco = (post_divm * (divn + 1)) +
+ ((post_divm * (u64)frac) /
+ FRAC_MAX);
+ if (vco < (PLL2000_VCO_MIN / 2) ||
+ vco > (PLL2000_VCO_MAX / 2)) {
+ frac++;
+ continue;
+ }
+ freq = vco / (divp + 1);
+ if (output_freq < freq)
+ diff = (u32)(freq - output_freq);
+ else
+ diff = (u32)(output_freq - freq);
+ if (diff < best_diff) {
+ pllcfg[PLLCFG_M] = divm;
+ pllcfg[PLLCFG_N] = divn;
+ pllcfg[PLLCFG_P] = divp;
+ *fracv = frac;
+
+ if (diff == 0) {
+ return 0;
+ }
+
+ best_diff = diff;
+ }
+ frac++;
+ }
+ }
+ }
+
+ if (best_diff == U32_MAX)
+ return -1;
+
+ return 0;
+}
+
+static void stm32mp1_ls_osc_set(int enable, fdt_addr_t rcc, u32 offset,
+ u32 mask_on)
+{
+ u32 address = rcc + offset;
+
+ if (enable)
+ setbits_le32(address, mask_on);
+ else
+ clrbits_le32(address, mask_on);
+}
+
+static void stm32mp1_hs_ocs_set(int enable, fdt_addr_t rcc, u32 mask_on)
+{
+ writel(mask_on, rcc + (enable ? RCC_OCENSETR : RCC_OCENCLRR));
+}
+
+static int stm32mp1_osc_wait(int enable, fdt_addr_t rcc, u32 offset,
+ u32 mask_rdy)
+{
+ u32 mask_test = 0;
+ u32 address = rcc + offset;
+ u32 val;
+ int ret;
+
+ if (enable)
+ mask_test = mask_rdy;
+
+ ret = readl_poll_timeout(address, val,
+ (val & mask_rdy) == mask_test,
+ TIMEOUT_1S);
+
+ if (ret)
+ log_err("OSC %x @ %x timeout for enable=%d : 0x%x\n",
+ mask_rdy, address, enable, readl(address));
+
+ return ret;
+}
+
+static void stm32mp1_lse_enable(fdt_addr_t rcc, int bypass, int digbyp,
+ u32 lsedrv)
+{
+ u32 value;
+
+ if (digbyp)
+ setbits_le32(rcc + RCC_BDCR, RCC_BDCR_DIGBYP);
+
+ if (bypass || digbyp)
+ setbits_le32(rcc + RCC_BDCR, RCC_BDCR_LSEBYP);
+
+ /*
+ * warning: not recommended to switch directly from "high drive"
+ * to "medium low drive", and vice-versa.
+ */
+ value = (readl(rcc + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK)
+ >> RCC_BDCR_LSEDRV_SHIFT;
+
+ while (value != lsedrv) {
+ if (value > lsedrv)
+ value--;
+ else
+ value++;
+
+ clrsetbits_le32(rcc + RCC_BDCR,
+ RCC_BDCR_LSEDRV_MASK,
+ value << RCC_BDCR_LSEDRV_SHIFT);
+ }
+
+ stm32mp1_ls_osc_set(1, rcc, RCC_BDCR, RCC_BDCR_LSEON);
+}
+
+static void stm32mp1_lse_wait(fdt_addr_t rcc)
+{
+ stm32mp1_osc_wait(1, rcc, RCC_BDCR, RCC_BDCR_LSERDY);
+}
+
+static void stm32mp1_lsi_set(fdt_addr_t rcc, int enable)
+{
+ stm32mp1_ls_osc_set(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSION);
+ stm32mp1_osc_wait(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSIRDY);
+}
+
+static void stm32mp1_hse_enable(fdt_addr_t rcc, int bypass, int digbyp, int css)
+{
+ if (digbyp)
+ writel(RCC_OCENR_DIGBYP, rcc + RCC_OCENSETR);
+ if (bypass || digbyp)
+ writel(RCC_OCENR_HSEBYP, rcc + RCC_OCENSETR);
+
+ stm32mp1_hs_ocs_set(1, rcc, RCC_OCENR_HSEON);
+ stm32mp1_osc_wait(1, rcc, RCC_OCRDYR, RCC_OCRDYR_HSERDY);
+
+ if (css)
+ writel(RCC_OCENR_HSECSSON, rcc + RCC_OCENSETR);
+}
+
+static void stm32mp1_csi_set(fdt_addr_t rcc, int enable)
+{
+ stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_CSION);
+ stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_CSIRDY);
+}
+
+static void stm32mp1_hsi_set(fdt_addr_t rcc, int enable)
+{
+ stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_HSION);
+ stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_HSIRDY);
+}
+
+static int stm32mp1_set_hsidiv(fdt_addr_t rcc, u8 hsidiv)
+{
+ u32 address = rcc + RCC_OCRDYR;
+ u32 val;
+ int ret;
+
+ clrsetbits_le32(rcc + RCC_HSICFGR,
+ RCC_HSICFGR_HSIDIV_MASK,
+ RCC_HSICFGR_HSIDIV_MASK & hsidiv);
+
+ ret = readl_poll_timeout(address, val,
+ val & RCC_OCRDYR_HSIDIVRDY,
+ TIMEOUT_200MS);
+ if (ret)
+ log_err("HSIDIV failed @ 0x%x: 0x%x\n",
+ address, readl(address));
+
+ return ret;
+}
+
+static int stm32mp1_hsidiv(fdt_addr_t rcc, ulong hsifreq)
+{
+ u8 hsidiv;
+ u32 hsidivfreq = MAX_HSI_HZ;
+
+ for (hsidiv = 0; hsidiv < 4; hsidiv++,
+ hsidivfreq = hsidivfreq / 2)
+ if (hsidivfreq == hsifreq)
+ break;
+
+ if (hsidiv == 4) {
+ log_err("hsi frequency invalid");
+ return -1;
+ }
+
+ if (hsidiv > 0)
+ return stm32mp1_set_hsidiv(rcc, hsidiv);
+
+ return 0;
+}
+
+static void pll_start(struct stm32mp_rcc_priv *priv, int pll_id)
+{
+ clrsetbits_le32((u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr,
+ RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
+ RCC_PLLNCR_DIVREN,
+ RCC_PLLNCR_PLLON);
+}
+
+static int pll_output(struct stm32mp_rcc_priv *priv, int pll_id, int output)
+{
+ u32 pllxcr = (u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr;
+ u32 val;
+ int ret;
+
+ ret = readl_poll_timeout(pllxcr, val, val & RCC_PLLNCR_PLLRDY,
+ TIMEOUT_200MS);
+
+ if (ret) {
+ log_err("PLL%d start failed @ 0x%x: 0x%x\n",
+ pll_id, pllxcr, readl(pllxcr));
+ return ret;
+ }
+
+ /* start the requested output */
+ setbits_le32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT);
+
+ return 0;
+}
+
+static int pll_stop(struct stm32mp_rcc_priv *priv, int pll_id)
+{
+ u32 pllxcr = (u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr;
+ u32 val;
+
+ /* stop all output */
+ clrbits_le32(pllxcr,
+ RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN);
+
+ /* stop PLL */
+ clrbits_le32(pllxcr, RCC_PLLNCR_PLLON);
+
+ /* wait PLL stopped */
+ return readl_poll_timeout(pllxcr, val, (val & RCC_PLLNCR_PLLRDY) == 0,
+ TIMEOUT_200MS);
+}
+
+static void pll_config_output(struct stm32mp_rcc_priv *priv,
+ int pll_id, u32 *pllcfg)
+{
+ fdt_addr_t rcc = (u32)(priv->base);
+ u32 value;
+
+ value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT)
+ & RCC_PLLNCFGR2_DIVP_MASK;
+ value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT)
+ & RCC_PLLNCFGR2_DIVQ_MASK;
+ value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT)
+ & RCC_PLLNCFGR2_DIVR_MASK;
+ writel(value, rcc + stm32mp1_clk_pll[pll_id].pllxcfgr2);
+}
+
+static int pll_config(struct stm32mp_rcc_priv *priv, int pll_id,
+ u32 *pllcfg, u32 fracv)
+{
+ fdt_addr_t rcc = (u32)(priv->base);
+ enum stm32mp1_plltype type = stm32mp1_clk_pll[pll_id].plltype;
+ int src;
+ ulong refclk;
+ u8 ifrge = 0;
+ u32 value;
+
+ src = readl((u32)(priv->base) + stm32mp1_clk_pll[pll_id].rckxselr) & RCC_SELR_SRC_MASK;
+ refclk = stm32mp1_clk_get_fixed(priv, stm32mp1_clk_pll[pll_id].refclk[src]) /
+ (pllcfg[PLLCFG_M] + 1);
+
+ if (refclk < (stm32mp1_pll[type].refclk_min * 1000000) ||
+ refclk > (stm32mp1_pll[type].refclk_max * 1000000)) {
+ log_err("invalid refclk = %x\n", (u32)refclk);
+ return -EINVAL;
+ }
+
+
+ if (type == PLL_800 && refclk >= 8000000)
+ ifrge = 1;
+
+ value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT)
+ & RCC_PLLNCFGR1_DIVN_MASK;
+ value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT)
+ & RCC_PLLNCFGR1_DIVM_MASK;
+ value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT)
+ & RCC_PLLNCFGR1_IFRGE_MASK;
+ writel(value, rcc + stm32mp1_clk_pll[pll_id].pllxcfgr1);
+
+ /* fractional configuration: load sigma-delta modulator (SDM) */
+
+ /* Write into FRACV the new fractional value , and FRACLE to 0 */
+ writel(fracv << RCC_PLLNFRACR_FRACV_SHIFT,
+ rcc + stm32mp1_clk_pll[pll_id].pllxfracr);
+
+ /* Write FRACLE to 1 : FRACV value is loaded into the SDM */
+ setbits_le32(rcc + stm32mp1_clk_pll[pll_id].pllxfracr,
+ RCC_PLLNFRACR_FRACLE);
+
+ pll_config_output(priv, pll_id, pllcfg);
+
+ return 0;
+}
+
+static void pll_csg(struct stm32mp_rcc_priv *priv, int pll_id, u32 *csg)
+{
+ u32 pllxcsg;
+
+ pllxcsg = ((csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
+ RCC_PLLNCSGR_MOD_PER_MASK) |
+ ((csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) &
+ RCC_PLLNCSGR_INC_STEP_MASK) |
+ ((csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
+ RCC_PLLNCSGR_SSCG_MODE_MASK);
+
+ writel(pllxcsg, (u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcsgr);
+
+ setbits_le32((u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr, RCC_PLLNCR_SSCG_CTRL);
+}
+
+static ulong pll_get_fref_ck(struct stm32mp_rcc_priv *priv,
+ int pll_id)
+{
+ u32 selr;
+ int src;
+
+ /* Get current refclk */
+ selr = readl(priv->base + stm32mp1_clk_pll[pll_id].rckxselr);
+ src = selr & RCC_SELR_SRC_MASK;
+
+ return stm32mp1_clk_get_fixed(priv, stm32mp1_clk_pll[pll_id].refclk[src]);
+}
+
+static __maybe_unused int pll_set_rate(struct udevice *dev,
+ int pll_id,
+ int div_id,
+ unsigned long clk_rate)
+{
+ struct stm32mp_rcc_priv *priv = dev_get_priv(dev);
+ unsigned int pllcfg[PLLCFG_NB];
+ ofnode plloff;
+ char name[12];
+ enum stm32mp1_plltype type = stm32mp1_clk_pll[pll_id].plltype;
+ int divm, divn, divy;
+ int ret;
+ ulong fck_ref;
+ u32 fracv;
+ u64 value;
+
+ if (div_id > _DIV_NB)
+ return -EINVAL;
+
+ sprintf(name, "st,pll@%d", pll_id);
+ plloff = dev_read_subnode(dev, name);
+ if (!ofnode_valid(plloff))
+ return -FDT_ERR_NOTFOUND;
+
+ ret = ofnode_read_u32_array(plloff, "cfg",
+ pllcfg, PLLCFG_NB);
+ if (ret < 0)
+ return -FDT_ERR_NOTFOUND;
+
+ fck_ref = pll_get_fref_ck(priv, pll_id);
+
+ divm = pllcfg[PLLCFG_M];
+ /* select output divider = 0: for _DIV_P, 1:_DIV_Q 2:_DIV_R */
+ divy = pllcfg[PLLCFG_P + div_id];
+
+ /* For: PLL1 & PLL2 => VCO is * 2 but ck_pll_y is also / 2
+ * So same final result than PLL2 et 4
+ * with FRACV
+ * Fck_pll_y = Fck_ref * ((DIVN + 1) + FRACV / 2^13)
+ * / (DIVy + 1) * (DIVM + 1)
+ * value = (DIVN + 1) * 2^13 + FRACV / 2^13
+ * = Fck_pll_y (DIVy + 1) * (DIVM + 1) * 2^13 / Fck_ref
+ */
+ value = ((u64)clk_rate * (divy + 1) * (divm + 1)) << 13;
+ value = lldiv(value, fck_ref);
+
+ divn = (value >> 13) - 1;
+ if (divn < DIVN_MIN ||
+ divn > stm32mp1_pll[type].divn_max) {
+ dev_err(dev, "divn invalid = %d", divn);
+ return -EINVAL;
+ }
+ fracv = value - ((divn + 1) << 13);
+ pllcfg[PLLCFG_N] = divn;
+
+ /* reconfigure PLL */
+ pll_stop(priv, pll_id);
+ pll_config(priv, pll_id, pllcfg, fracv);
+ pll_start(priv, pll_id);
+ pll_output(priv, pll_id, pllcfg[PLLCFG_O]);
+
+ return 0;
+}
+
+static int set_clksrc(struct stm32mp_rcc_priv *priv, unsigned int clksrc)
+{
+ u32 address = (u32)(priv->base);
+ u32 mux = (clksrc & MUX_ID_MASK) >> MUX_ID_SHIFT;
+ u32 val;
+ int ret;
+
+ /* List of relevant muxes to keep the size down */
+ if (mux == MUX_PLL12)
+ address += RCC_RCK12SELR;
+ else if (mux == MUX_PLL3)
+ address += RCC_RCK3SELR;
+ else if (mux == MUX_PLL4)
+ address += RCC_RCK4SELR;
+ else if (mux == MUX_MPU)
+ address += RCC_MPCKSELR;
+ else if (mux == MUX_AXI)
+ address += RCC_ASSCKSELR;
+ else if (mux == MUX_MLAHB)
+ address += RCC_MSSCKSELR;
+ else if (mux == MUX_CKPER)
+ address += RCC_CPERCKSELR;
+ else
+ return -EINVAL;
+
+ clrsetbits_le32(address, RCC_SELR_SRC_MASK, clksrc & RCC_SELR_SRC_MASK);
+ ret = readl_poll_timeout(address, val, val & RCC_SELR_SRCRDY,
+ TIMEOUT_200MS);
+ if (ret)
+ log_err("CLKSRC %x start failed @ 0x%x: 0x%x\n",
+ clksrc, address, readl(address));
+
+ return ret;
+}
+
+static void stgen_config(struct stm32mp_rcc_priv *priv)
+{
+ u32 stgenc, cntfid0;
+ ulong rate = clk_get_rate(&priv->osc_clk[_HSI]);
+ stgenc = STM32_STGEN_BASE;
+ cntfid0 = readl(stgenc + STGENC_CNTFID0);
+
+ if (cntfid0 != rate) {
+ u64 counter;
+
+ log_debug("System Generic Counter (STGEN) update\n");
+ clrbits_le32(stgenc + STGENC_CNTCR, STGENC_CNTCR_EN);
+ counter = (u64)readl(stgenc + STGENC_CNTCVL);
+ counter |= ((u64)(readl(stgenc + STGENC_CNTCVU))) << 32;
+ counter = lldiv(counter * (u64)rate, cntfid0);
+ writel((u32)counter, stgenc + STGENC_CNTCVL);
+ writel((u32)(counter >> 32), stgenc + STGENC_CNTCVU);
+ writel(rate, stgenc + STGENC_CNTFID0);
+ setbits_le32(stgenc + STGENC_CNTCR, STGENC_CNTCR_EN);
+
+ __asm__ volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (rate));
+
+ /* need to update gd->arch.timer_rate_hz with new frequency */
+ timer_init();
+ }
+}
+
+static int set_clkdiv(unsigned int clkdiv, u32 address)
+{
+ u32 val;
+ int ret;
+
+
+ clrsetbits_le32(address, RCC_DIVR_DIV_MASK, clkdiv & RCC_DIVR_DIV_MASK);
+ ret = readl_poll_timeout(address, val, val & RCC_DIVR_DIVRDY,
+ TIMEOUT_200MS);
+ if (ret)
+ log_err("CLKDIV %x start failed @ 0x%x: 0x%x\n",
+ clkdiv, address, readl(address));
+
+ return ret;
+}
+
+static void set_rtcsrc(struct stm32mp_rcc_priv *priv,
+ unsigned int clksrc,
+ int lse_css)
+{
+ u32 address = (u32)(priv->base) + RCC_BDCR;
+
+ if (readl(address) & RCC_BDCR_RTCCKEN)
+ goto skip_rtc;
+
+ if (clksrc == CLK_RTC_DISABLED)
+ goto skip_rtc;
+
+ clrsetbits_le32(address,
+ RCC_BDCR_RTCSRC_MASK,
+ clksrc << RCC_BDCR_RTCSRC_SHIFT);
+
+ setbits_le32(address, RCC_BDCR_RTCCKEN);
+
+skip_rtc:
+ if (lse_css)
+ setbits_le32(address, RCC_BDCR_LSECSSON);
+}
+
+static void pkcs_config(struct stm32mp_rcc_priv *priv, u32 pkcs)
+{
+ u32 mux = (pkcs & MUX_ID_MASK) >> MUX_ID_SHIFT;
+ u32 address = (u32)(priv->base) + stm32mp13_muxes[mux].reg_off;
+ u32 mask = (BIT(stm32mp13_muxes[mux].width) - 1) << stm32mp13_muxes[mux].shift;
+ u32 value = (pkcs << stm32mp13_muxes[mux].shift) & mask;
+
+ clrsetbits_le32(address, mask, value);
+}
+
+static int stm32mp1_clktree(struct udevice *dev)
+{
+ struct stm32mp_rcc_priv *priv = dev_get_priv(dev);
+ fdt_addr_t rcc = (u32)(priv->base);
+ unsigned int clksrc[CLKSRC_NB];
+ unsigned int clkdiv[CLKDIV_NB];
+ unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
+ unsigned int pllfracv[_PLL_NB];
+ unsigned int pllcsg[_PLL_NB][PLLCSG_NB];
+ bool pllcfg_valid[_PLL_NB];
+ bool pllcsg_set[_PLL_NB];
+ int ret;
+ int i, len;
+ int lse_css = 0;
+ const u32 *pkcs_cell;
+
+ /* check mandatory field */
+ ret = dev_read_u32_array(dev, "st,clksrc", clksrc, CLKSRC_NB);
+ if (ret < 0) {
+ dev_dbg(dev, "field st,clksrc invalid: error %d\n", ret);
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ ret = dev_read_u32_array(dev, "st,clkdiv", clkdiv, CLKDIV_NB);
+ if (ret < 0) {
+ dev_dbg(dev, "field st,clkdiv invalid: error %d\n", ret);
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ /* check mandatory field in each pll */
+ for (i = 0; i < _PLL_NB; i++) {
+ char name[12];
+ ofnode node;
+
+ sprintf(name, "st,pll@%d", i);
+ node = dev_read_subnode(dev, name);
+ pllcfg_valid[i] = ofnode_valid(node);
+ pllcsg_set[i] = false;
+ if (pllcfg_valid[i]) {
+ dev_dbg(dev, "DT for PLL %d @ %s\n", i, name);
+ ret = ofnode_read_u32_array(node, "cfg",
+ pllcfg[i], PLLCFG_NB);
+ if (ret < 0) {
+ dev_dbg(dev, "field cfg invalid: error %d\n", ret);
+ return -FDT_ERR_NOTFOUND;
+ }
+ pllfracv[i] = ofnode_read_u32_default(node, "frac", 0);
+
+ ret = ofnode_read_u32_array(node, "csg", pllcsg[i],
+ PLLCSG_NB);
+ if (!ret) {
+ pllcsg_set[i] = true;
+ } else if (ret != -FDT_ERR_NOTFOUND) {
+ dev_dbg(dev, "invalid csg node for pll@%d res=%d\n",
+ i, ret);
+ return ret;
+ }
+ } else if (i == _PLL1) {
+ /* use OPP for PLL1 for A7 CPU */
+ dev_dbg(dev, "DT for PLL %d with OPP\n", i);
+ ret = stm32mp1_pll1_opp(priv,
+ clksrc[CLKSRC_PLL12],
+ pllcfg[i],
+ &pllfracv[i]);
+ if (ret) {
+ dev_dbg(dev, "PLL %d with OPP error = %d\n", i, ret);
+ return ret;
+ }
+ pllcfg_valid[i] = true;
+ }
+ }
+
+ dev_dbg(dev, "switch ON osillator\n");
+ /*
+ * switch ON oscillator found in device-tree,
+ * HSI already ON after bootrom
+ */
+ if (clk_valid(&priv->osc_clk[_LSI]))
+ stm32mp1_lsi_set(rcc, 1);
+
+ if (clk_valid(&priv->osc_clk[_LSE])) {
+ int bypass, digbyp;
+ u32 lsedrv;
+ struct udevice *dev = priv->osc_clk[_LSE].dev;
+
+ bypass = dev_read_bool(dev, "st,bypass");
+ digbyp = dev_read_bool(dev, "st,digbypass");
+ lse_css = dev_read_bool(dev, "st,css");
+ lsedrv = dev_read_u32_default(dev, "st,drive",
+ LSEDRV_MEDIUM_HIGH);
+
+ stm32mp1_lse_enable(rcc, bypass, digbyp, lsedrv);
+ }
+
+
+ if (clk_valid(&priv->osc_clk[_HSE])) {
+ int bypass, digbyp, css;
+ struct udevice *dev = priv->osc_clk[_HSE].dev;
+
+ bypass = dev_read_bool(dev, "st,bypass");
+ digbyp = dev_read_bool(dev, "st,digbypass");
+ css = dev_read_bool(dev, "st,css");
+
+ stm32mp1_hse_enable(rcc, bypass, digbyp, css);
+ }
+
+ /* CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
+ * => switch on CSI even if node is not present in device tree
+ */
+ stm32mp1_csi_set(rcc, 1);
+
+ /* come back to HSI */
+ dev_dbg(dev, "come back to HSI\n");
+ set_clksrc(priv, CLK_MPU_HSI);
+ set_clksrc(priv, CLK_AXI_HSI);
+ set_clksrc(priv, CLK_MLAHBS_HSI);
+
+ dev_dbg(dev, "pll stop\n");
+ for (i = 0; i < _PLL_NB; i++)
+ pll_stop(priv, i);
+
+ /* configure HSIDIV */
+ dev_dbg(dev, "configure HSIDIV\n");
+ if (clk_valid(&priv->osc_clk[_HSI])) {
+ stm32mp1_hsidiv(rcc, clk_get_rate(&priv->osc_clk[_HSI]));
+ stgen_config(priv);
+ }
+
+ /* select DIV */
+ dev_dbg(dev, "select DIV\n");
+ /* no ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
+ set_clkdiv(clkdiv[CLKDIV_AXI], rcc + RCC_AXIDIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB4], rcc + RCC_APB4DIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB5], rcc + RCC_APB5DIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB6], rcc + RCC_APB6DIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB1], rcc + RCC_APB1DIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB2], rcc + RCC_APB2DIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB3], rcc + RCC_APB3DIVR);
+
+ /* no ready bit for RTC */
+ writel(clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK, rcc + RCC_RTCDIVR);
+
+ /* configure PLLs source */
+ dev_dbg(dev, "configure PLLs source\n");
+ set_clksrc(priv, clksrc[CLKSRC_PLL12]);
+ set_clksrc(priv, clksrc[CLKSRC_PLL3]);
+ set_clksrc(priv, clksrc[CLKSRC_PLL4]);
+
+ /* configure and start PLLs */
+ dev_dbg(dev, "configure PLLs\n");
+ for (i = 0; i < _PLL_NB; i++) {
+ if (!pllcfg_valid[i])
+ continue;
+ dev_dbg(dev, "configure PLL %d\n", i);
+ pll_config(priv, i, pllcfg[i], pllfracv[i]);
+ if (pllcsg_set[i])
+ pll_csg(priv, i, pllcsg[i]);
+ pll_start(priv, i);
+ }
+
+ /* wait and start PLLs ouptut when ready */
+ for (i = 0; i < _PLL_NB; i++) {
+ if (!pllcfg_valid[i])
+ continue;
+ dev_dbg(dev, "output PLL %d\n", i);
+ pll_output(priv, i, pllcfg[i][PLLCFG_O]);
+ }
+
+ /* wait LSE ready before to use it */
+ if (clk_valid(&priv->osc_clk[_LSE]))
+ stm32mp1_lse_wait(rcc);
+
+ /* configure with expected clock source */
+ dev_dbg(dev, "CLKSRC\n");
+ set_clksrc(priv, clksrc[CLKSRC_MPU]);
+ set_clksrc(priv, clksrc[CLKSRC_AXI]);
+ set_clksrc(priv, clksrc[CLKSRC_MLAHB]);
+ set_rtcsrc(priv, clksrc[CLKSRC_RTC], lse_css);
+
+ /* configure PKCK */
+ dev_dbg(dev, "PKCK\n");
+ pkcs_cell = dev_read_prop(dev, "st,pkcs", &len);
+ if (pkcs_cell) {
+ bool ckper_disabled = false;
+
+ for (i = 0; i < len / sizeof(u32); i++) {
+ u32 pkcs = (u32)fdt32_to_cpu(pkcs_cell[i]);
+
+ if (pkcs == CLK_CKPER_DISABLED) {
+ ckper_disabled = true;
+ continue;
+ }
+ pkcs_config(priv, pkcs);
+ }
+ /* CKPER is source for some peripheral clock
+ * (FMC-NAND / QPSI-NOR) and switching source is allowed
+ * only if previous clock is still ON
+ * => deactivated CKPER only after switching clock
+ */
+ if (ckper_disabled)
+ pkcs_config(priv, CLK_CKPER_DISABLED);
+ }
+
+ /* STGEN clock source can change with CLK_STGEN_XXX */
+ stgen_config(priv);
+
+ dev_dbg(dev, "oscillator off\n");
+ /* switch OFF HSI if not found in device-tree */
+ if (!clk_valid(&priv->osc_clk[_HSI]))
+ stm32mp1_hsi_set(rcc, 0);
+
+ /* Software Self-Refresh mode (SSR) during DDR initilialization */
+ clrsetbits_le32((u32)(priv->base) + RCC_DDRITFCR,
+ RCC_DDRITFCR_DDRCKMOD_MASK,
+ RCC_DDRITFCR_DDRCKMOD_SSR <<
+ RCC_DDRITFCR_DDRCKMOD_SHIFT);
+
+ return 0;
+}
+#endif
+
+static int stm32mp1_osc_init(struct udevice *dev)
+{
+ struct stm32mp_rcc_priv *priv = dev_get_priv(dev);
+ fdt_addr_t base = dev_read_addr(dev->parent);
+ struct clk *ck;
+ int i;
+
+ const char *name[NB_OSC] = {
+ [_LSI] = "lsi",
+ [_LSE] = "lse",
+ [_HSI] = "hsi",
+ [_HSE] = "hse",
+ [_CSI] = "csi",
+ [_I2S_CKIN] = "i2s_ckin",
+ };
+
+ const struct {
+ const char *name;
+ const int rate;
+ } fixed_clk[] = {
+ { "bsec", 66625000 },
+ { "ck_axi", 266500000 },
+ { "ck_mlahb", 200000000 },
+ { "ck_mpu", 1000000000 },
+ { "ck_per", 24000000 },
+ { "ck_rtc", 32768 },
+ { "clk-hse-div2", 12000000 },
+ { "pclk1", 100000000 },
+ { "pclk2", 100000000 },
+ { "pclk3", 100000000 },
+ { "pclk4", 133250000 },
+ { "pclk5", 66625000 },
+ { "pclk6", 100000000 },
+ { "pll2_q", 266500000 },
+ { "pll2_r", 533000000 },
+ { "pll3_p", 200000000 },
+ { "pll3_q", 150000000 },
+ { "pll3_r", 200000000 },
+ { "pll4_p", 125000000 },
+ { "pll4_q", 83333333 },
+ { "pll4_r", 75000000 },
+ { "rtcapb", 66625000 },
+ { "timg1_ck", 200000000 },
+ { "timg2_ck", 200000000 },
+ { "timg3_ck", 200000000 },
+ };
+
+ if (base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->base = (void __iomem *)base;
+
+ for (i = 0; i < NB_OSC; i++) {
+ if (clk_get_by_name(dev, name[i], &priv->osc_clk[i]))
+ dev_dbg(dev, "No source clock \"%s\"\n", name[i]);
+ else
+ dev_dbg(dev, "%s clock rate: %luHz\n",
+ name[i], clk_get_rate(&priv->osc_clk[i]));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(fixed_clk); i++) {
+ ck = clk_register_fixed_rate(NULL, fixed_clk[i].name, fixed_clk[i].rate);
+ if (!ck)
+ dev_dbg(dev, "Cannot register fixed clock \"%s\"\n", fixed_clk[i].name);
+ }
+
+ return 0;
+}
+#endif
+
static int stm32mp1_clk_probe(struct udevice *dev)
{
- struct udevice *scmi;
int err;
+#ifdef CONFIG_TFABOOT
+ struct udevice *scmi;
+
/* force SCMI probe to register all SCMI clocks */
uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(scmi_clock), &scmi);
+#else
+ err = stm32mp1_osc_init(dev);
+ if (err)
+ return err;
+
+#if defined(CONFIG_XPL_BUILD)
+ /* clock tree init is done only one time, before relocation */
+ if (!(gd->flags & GD_FLG_RELOC))
+ err = stm32mp1_clktree(dev);
+ if (err)
+ dev_err(dev, "clock tree initialization failed (%d)\n", err);
+#endif
+#endif
err = stm32_rcc_init(dev, &stm32mp13_data);
if (err)
@@ -815,6 +2012,7 @@ static int stm32mp1_clk_probe(struct udevice *dev)
/* DDRPHYC father */
gd->mem_clk = clk_stm32_get_rate_by_name("pll2_r");
+#ifndef CONFIG_XPL_BUILD
if (IS_ENABLED(CONFIG_DISPLAY_CPUINFO)) {
if (gd->flags & GD_FLG_RELOC) {
char buf[32];
@@ -827,6 +2025,7 @@ static int stm32mp1_clk_probe(struct udevice *dev)
log_info("- DDR : %s MHz\n", strmhz(buf, gd->mem_clk));
}
}
+#endif
return 0;
}
diff --git a/drivers/clk/stm32/stm32mp13_rcc.h b/drivers/clk/stm32/stm32mp13_rcc.h
index e7191b428af..b9b44b213c3 100644
--- a/drivers/clk/stm32/stm32mp13_rcc.h
+++ b/drivers/clk/stm32/stm32mp13_rcc.h
@@ -285,4 +285,97 @@
#define RCC_AHB6SECSR_ETH2MACSECF 30
#define RCC_AHB6SECSR_ETH2STPSECF 31
+/* Fields of RCC_BDCR register */
+#define RCC_BDCR_LSEON BIT(0)
+#define RCC_BDCR_LSEBYP BIT(1)
+#define RCC_BDCR_LSERDY BIT(2)
+#define RCC_BDCR_DIGBYP BIT(3)
+#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4)
+#define RCC_BDCR_LSEDRV_SHIFT 4
+#define RCC_BDCR_LSECSSON BIT(8)
+#define RCC_BDCR_RTCCKEN BIT(20)
+#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16)
+#define RCC_BDCR_RTCSRC_SHIFT 16
+
+/* Fields of RCC_RDLSICR register */
+#define RCC_RDLSICR_LSION BIT(0)
+#define RCC_RDLSICR_LSIRDY BIT(1)
+
+/* used for ALL PLLNCR registers */
+#define RCC_PLLNCR_PLLON BIT(0)
+#define RCC_PLLNCR_PLLRDY BIT(1)
+#define RCC_PLLNCR_SSCG_CTRL BIT(2)
+#define RCC_PLLNCR_DIVPEN BIT(4)
+#define RCC_PLLNCR_DIVQEN BIT(5)
+#define RCC_PLLNCR_DIVREN BIT(6)
+#define RCC_PLLNCR_DIVEN_SHIFT 4
+
+/* used for ALL PLLNCFGR1 registers */
+#define RCC_PLLNCFGR1_DIVM_SHIFT 16
+#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16)
+#define RCC_PLLNCFGR1_DIVN_SHIFT 0
+#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0)
+/* only for PLL3 and PLL4 */
+#define RCC_PLLNCFGR1_IFRGE_SHIFT 24
+#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24)
+
+/* used for ALL PLLNCFGR2 registers , using stm32mp1_div_id */
+#define RCC_PLLNCFGR2_SHIFT(div_id) ((div_id) * 8)
+#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0)
+#define RCC_PLLNCFGR2_DIVP_SHIFT RCC_PLLNCFGR2_SHIFT(_DIV_P)
+#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0)
+#define RCC_PLLNCFGR2_DIVQ_SHIFT RCC_PLLNCFGR2_SHIFT(_DIV_Q)
+#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8)
+#define RCC_PLLNCFGR2_DIVR_SHIFT RCC_PLLNCFGR2_SHIFT(_DIV_R)
+#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16)
+
+/* used for ALL PLLNFRACR registers */
+#define RCC_PLLNFRACR_FRACV_SHIFT 3
+#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3)
+#define RCC_PLLNFRACR_FRACLE BIT(16)
+
+/* used for ALL PLLNCSGR registers */
+#define RCC_PLLNCSGR_INC_STEP_SHIFT 16
+#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16)
+#define RCC_PLLNCSGR_MOD_PER_SHIFT 0
+#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0)
+#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15
+#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15)
+
+/* used for RCC_OCENSETR and RCC_OCENCLRR registers */
+#define RCC_OCENR_HSION BIT(0)
+#define RCC_OCENR_CSION BIT(4)
+#define RCC_OCENR_DIGBYP BIT(7)
+#define RCC_OCENR_HSEON BIT(8)
+#define RCC_OCENR_HSEBYP BIT(10)
+#define RCC_OCENR_HSECSSON BIT(11)
+
+/* Fields of RCC_OCRDYR register */
+#define RCC_OCRDYR_HSIRDY BIT(0)
+#define RCC_OCRDYR_HSIDIVRDY BIT(2)
+#define RCC_OCRDYR_CSIRDY BIT(4)
+#define RCC_OCRDYR_HSERDY BIT(8)
+
+/* Fields of DDRITFCR register */
+#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20)
+#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20
+#define RCC_DDRITFCR_DDRCKMOD_SSR 0
+
+/* Fields of RCC_HSICFGR register */
+#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0)
+
+/* used for MCO related operations */
+#define RCC_MCOCFG_MCOON BIT(12)
+#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4)
+#define RCC_MCOCFG_MCODIV_SHIFT 4
+#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0)
+
+/* used for most of SELR register */
+#define RCC_SELR_SRC_MASK GENMASK(2, 0)
+#define RCC_SELR_SRCRDY BIT(31)
+
+/* used for most of DIVR register : max div for RTC */
+#define RCC_DIVR_DIV_MASK GENMASK(5, 0)
+#define RCC_DIVR_DIVRDY BIT(31)
+
#endif /* STM32MP13_RCC_H */
diff --git a/include/dt-bindings/clock/stm32mp13-clksrc.h b/include/dt-bindings/clock/stm32mp13-clksrc.h
new file mode 100644
index 00000000000..312a6054699
--- /dev/null
+++ b/include/dt-bindings/clock/stm32mp13-clksrc.h
@@ -0,0 +1,399 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ *
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_
+#define _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_
+
+/* PLL output is enable when x=1, with x=p,q or r */
+#define PQR(p, q, r) (((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2))
+
+/* st,clksrc: mandatory clock source */
+
+#define CMD_DIV 0
+#define CMD_MUX 1
+#define CMD_CLK 2
+#define CMD_RESERVED1 3
+
+#define CMD_SHIFT 26
+#define CMD_MASK 0xFC000000
+#define CMD_DATA_MASK 0x03FFFFFF
+
+#define DIV_ID_SHIFT 8
+#define DIV_ID_MASK 0x0000FF00
+
+#define DIV_DIVN_SHIFT 0
+#define DIV_DIVN_MASK 0x000000FF
+
+#define MUX_ID_SHIFT 4
+#define MUX_ID_MASK 0x00000FF0
+
+#define MUX_SEL_SHIFT 0
+#define MUX_SEL_MASK 0x0000000F
+
+#define CLK_ID_MASK GENMASK_32(19, 11)
+#define CLK_ID_SHIFT 11
+#define CLK_ON_MASK 0x00000400
+#define CLK_ON_SHIFT 10
+#define CLK_DIV_MASK GENMASK_32(9, 4)
+#define CLK_DIV_SHIFT 4
+#define CLK_SEL_MASK GENMASK_32(3, 0)
+#define CLK_SEL_SHIFT 0
+
+#define DIV_PLL1DIVP 0
+#define DIV_PLL2DIVP 1
+#define DIV_PLL2DIVQ 2
+#define DIV_PLL2DIVR 3
+#define DIV_PLL3DIVP 4
+#define DIV_PLL3DIVQ 5
+#define DIV_PLL3DIVR 6
+#define DIV_PLL4DIVP 7
+#define DIV_PLL4DIVQ 8
+#define DIV_PLL4DIVR 9
+#define DIV_MPU 10
+#define DIV_AXI 11
+#define DIV_MLAHB 12
+#define DIV_APB1 13
+#define DIV_APB2 14
+#define DIV_APB3 15
+#define DIV_APB4 16
+#define DIV_APB5 17
+#define DIV_APB6 18
+#define DIV_RTC 19
+#define DIV_MCO1 20
+#define DIV_MCO2 21
+#define DIV_HSI 22
+#define DIV_TRACE 23
+#define DIV_ETH1PTP 24
+#define DIV_ETH2PTP 25
+#define DIV_MAX 26
+
+#define DIV(div_id, div) ((CMD_DIV << CMD_SHIFT) |\
+ ((div_id) << DIV_ID_SHIFT |\
+ (div)))
+
+#define CLKSRC(mux_id, sel) ((CMD_MUX << CMD_SHIFT) |\
+ ((mux_id) << MUX_ID_SHIFT |\
+ (sel)))
+
+/* MCO output is enable */
+#define MCO_SRC(mco_id, sel) ((CMD_CLK << CMD_SHIFT) |\
+ (((mco_id) << CLK_ID_SHIFT) |\
+ (sel)) | CLK_ON_MASK)
+
+#define MCO_DISABLED(mco_id) ((CMD_CLK << CMD_SHIFT) |\
+ ((mco_id) << CLK_ID_SHIFT))
+
+/* CLK output is enable */
+#define CLK_SRC(clk_id, sel) ((CMD_CLK << CMD_SHIFT) |\
+ (((clk_id) << CLK_ID_SHIFT) |\
+ (sel)) | CLK_ON_MASK)
+
+#define CLK_DISABLED(clk_id) ((CMD_CLK << CMD_SHIFT) |\
+ ((clk_id) << CLK_ID_SHIFT))
+
+#define MUX_MPU 0
+#define MUX_AXI 1
+#define MUX_MLAHB 2
+#define MUX_PLL12 3
+#define MUX_PLL3 4
+#define MUX_PLL4 5
+#define MUX_RTC 6
+#define MUX_MCO1 7
+#define MUX_MCO2 8
+#define MUX_CKPER 9
+#define MUX_KERNEL_BEGIN 10
+#define MUX_ADC1 10
+#define MUX_ADC2 11
+#define MUX_DCMIPP 12
+#define MUX_ETH1 13
+#define MUX_ETH2 14
+#define MUX_FDCAN 15
+#define MUX_FMC 16
+#define MUX_I2C12 17
+#define MUX_I2C3 18
+#define MUX_I2C4 19
+#define MUX_I2C5 20
+#define MUX_LPTIM1 21
+#define MUX_LPTIM2 22
+#define MUX_LPTIM3 23
+#define MUX_LPTIM45 24
+#define MUX_QSPI 25
+#define MUX_RNG1 26
+#define MUX_SAES 27
+#define MUX_SAI1 28
+#define MUX_SAI2 29
+#define MUX_SDMMC1 30
+#define MUX_SDMMC2 31
+#define MUX_SPDIF 32
+#define MUX_SPI1 33
+#define MUX_SPI23 34
+#define MUX_SPI4 35
+#define MUX_SPI5 36
+#define MUX_STGEN 37
+#define MUX_UART1 38
+#define MUX_UART2 39
+#define MUX_UART35 40
+#define MUX_UART4 41
+#define MUX_UART6 42
+#define MUX_UART78 43
+#define MUX_USBO 44
+#define MUX_USBPHY 45
+#define MUX_MAX 46
+
+#define CLK_MPU_HSI CLKSRC(MUX_MPU, 0)
+#define CLK_MPU_HSE CLKSRC(MUX_MPU, 1)
+#define CLK_MPU_PLL1P CLKSRC(MUX_MPU, 2)
+#define CLK_MPU_PLL1P_DIV CLKSRC(MUX_MPU, 3)
+
+#define CLK_AXI_HSI CLKSRC(MUX_AXI, 0)
+#define CLK_AXI_HSE CLKSRC(MUX_AXI, 1)
+#define CLK_AXI_PLL2P CLKSRC(MUX_AXI, 2)
+
+#define CLK_MLAHBS_HSI CLKSRC(MUX_MLAHB, 0)
+#define CLK_MLAHBS_HSE CLKSRC(MUX_MLAHB, 1)
+#define CLK_MLAHBS_CSI CLKSRC(MUX_MLAHB, 2)
+#define CLK_MLAHBS_PLL3 CLKSRC(MUX_MLAHB, 3)
+
+#define CLK_PLL12_HSI CLKSRC(MUX_PLL12, 0)
+#define CLK_PLL12_HSE CLKSRC(MUX_PLL12, 1)
+
+#define CLK_PLL3_HSI CLKSRC(MUX_PLL3, 0)
+#define CLK_PLL3_HSE CLKSRC(MUX_PLL3, 1)
+#define CLK_PLL3_CSI CLKSRC(MUX_PLL3, 2)
+
+#define CLK_PLL4_HSI CLKSRC(MUX_PLL4, 0)
+#define CLK_PLL4_HSE CLKSRC(MUX_PLL4, 1)
+#define CLK_PLL4_CSI CLKSRC(MUX_PLL4, 2)
+
+#define CLK_RTC_DISABLED CLK_DISABLED(RTC)
+#define CLK_RTC_LSE CLK_SRC(RTC, 1)
+#define CLK_RTC_LSI CLK_SRC(RTC, 2)
+#define CLK_RTC_HSE CLK_SRC(RTC, 3)
+
+#define CLK_MCO1_HSI CLK_SRC(CK_MCO1, 0)
+#define CLK_MCO1_HSE CLK_SRC(CK_MCO1, 1)
+#define CLK_MCO1_CSI CLK_SRC(CK_MCO1, 2)
+#define CLK_MCO1_LSI CLK_SRC(CK_MCO1, 3)
+#define CLK_MCO1_LSE CLK_SRC(CK_MCO1, 4)
+#define CLK_MCO1_DISABLED CLK_DISABLED(CK_MCO1)
+
+#define CLK_MCO2_MPU CLK_SRC(CK_MCO2, 0)
+#define CLK_MCO2_AXI CLK_SRC(CK_MCO2, 1)
+#define CLK_MCO2_MLAHB CLK_SRC(CK_MCO2, 2)
+#define CLK_MCO2_PLL4 CLK_SRC(CK_MCO2, 3)
+#define CLK_MCO2_HSE CLK_SRC(CK_MCO2, 4)
+#define CLK_MCO2_HSI CLK_SRC(CK_MCO2, 5)
+#define CLK_MCO2_DISABLED CLK_DISABLED(CK_MCO2)
+
+#define CLK_CKPER_HSI CLKSRC(MUX_CKPER, 0)
+#define CLK_CKPER_CSI CLKSRC(MUX_CKPER, 1)
+#define CLK_CKPER_HSE CLKSRC(MUX_CKPER, 2)
+#define CLK_CKPER_DISABLED CLKSRC(MUX_CKPER, 3)
+
+#define CLK_I2C12_PCLK1 CLKSRC(MUX_I2C12, 0)
+#define CLK_I2C12_PLL4R CLKSRC(MUX_I2C12, 1)
+#define CLK_I2C12_HSI CLKSRC(MUX_I2C12, 2)
+#define CLK_I2C12_CSI CLKSRC(MUX_I2C12, 3)
+
+#define CLK_I2C3_PCLK6 CLKSRC(MUX_I2C3, 0)
+#define CLK_I2C3_PLL4R CLKSRC(MUX_I2C3, 1)
+#define CLK_I2C3_HSI CLKSRC(MUX_I2C3, 2)
+#define CLK_I2C3_CSI CLKSRC(MUX_I2C3, 3)
+
+#define CLK_I2C4_PCLK6 CLKSRC(MUX_I2C4, 0)
+#define CLK_I2C4_PLL4R CLKSRC(MUX_I2C4, 1)
+#define CLK_I2C4_HSI CLKSRC(MUX_I2C4, 2)
+#define CLK_I2C4_CSI CLKSRC(MUX_I2C4, 3)
+
+#define CLK_I2C5_PCLK6 CLKSRC(MUX_I2C5, 0)
+#define CLK_I2C5_PLL4R CLKSRC(MUX_I2C5, 1)
+#define CLK_I2C5_HSI CLKSRC(MUX_I2C5, 2)
+#define CLK_I2C5_CSI CLKSRC(MUX_I2C5, 3)
+
+#define CLK_SPI1_PLL4P CLKSRC(MUX_SPI1, 0)
+#define CLK_SPI1_PLL3Q CLKSRC(MUX_SPI1, 1)
+#define CLK_SPI1_I2SCKIN CLKSRC(MUX_SPI1, 2)
+#define CLK_SPI1_CKPER CLKSRC(MUX_SPI1, 3)
+#define CLK_SPI1_PLL3R CLKSRC(MUX_SPI1, 4)
+
+#define CLK_SPI23_PLL4P CLKSRC(MUX_SPI23, 0)
+#define CLK_SPI23_PLL3Q CLKSRC(MUX_SPI23, 1)
+#define CLK_SPI23_I2SCKIN CLKSRC(MUX_SPI23, 2)
+#define CLK_SPI23_CKPER CLKSRC(MUX_SPI23, 3)
+#define CLK_SPI23_PLL3R CLKSRC(MUX_SPI23, 4)
+
+#define CLK_SPI4_PCLK6 CLKSRC(MUX_SPI4, 0)
+#define CLK_SPI4_PLL4Q CLKSRC(MUX_SPI4, 1)
+#define CLK_SPI4_HSI CLKSRC(MUX_SPI4, 2)
+#define CLK_SPI4_CSI CLKSRC(MUX_SPI4, 3)
+#define CLK_SPI4_HSE CLKSRC(MUX_SPI4, 4)
+#define CLK_SPI4_I2SCKIN CLKSRC(MUX_SPI4, 5)
+
+#define CLK_SPI5_PCLK6 CLKSRC(MUX_SPI5, 0)
+#define CLK_SPI5_PLL4Q CLKSRC(MUX_SPI5, 1)
+#define CLK_SPI5_HSI CLKSRC(MUX_SPI5, 2)
+#define CLK_SPI5_CSI CLKSRC(MUX_SPI5, 3)
+#define CLK_SPI5_HSE CLKSRC(MUX_SPI5, 4)
+
+#define CLK_UART1_PCLK6 CLKSRC(MUX_UART1, 0)
+#define CLK_UART1_PLL3Q CLKSRC(MUX_UART1, 1)
+#define CLK_UART1_HSI CLKSRC(MUX_UART1, 2)
+#define CLK_UART1_CSI CLKSRC(MUX_UART1, 3)
+#define CLK_UART1_PLL4Q CLKSRC(MUX_UART1, 4)
+#define CLK_UART1_HSE CLKSRC(MUX_UART1, 5)
+
+#define CLK_UART2_PCLK6 CLKSRC(MUX_UART2, 0)
+#define CLK_UART2_PLL3Q CLKSRC(MUX_UART2, 1)
+#define CLK_UART2_HSI CLKSRC(MUX_UART2, 2)
+#define CLK_UART2_CSI CLKSRC(MUX_UART2, 3)
+#define CLK_UART2_PLL4Q CLKSRC(MUX_UART2, 4)
+#define CLK_UART2_HSE CLKSRC(MUX_UART2, 5)
+
+#define CLK_UART35_PCLK1 CLKSRC(MUX_UART35, 0)
+#define CLK_UART35_PLL4Q CLKSRC(MUX_UART35, 1)
+#define CLK_UART35_HSI CLKSRC(MUX_UART35, 2)
+#define CLK_UART35_CSI CLKSRC(MUX_UART35, 3)
+#define CLK_UART35_HSE CLKSRC(MUX_UART35, 4)
+
+#define CLK_UART4_PCLK1 CLKSRC(MUX_UART4, 0)
+#define CLK_UART4_PLL4Q CLKSRC(MUX_UART4, 1)
+#define CLK_UART4_HSI CLKSRC(MUX_UART4, 2)
+#define CLK_UART4_CSI CLKSRC(MUX_UART4, 3)
+#define CLK_UART4_HSE CLKSRC(MUX_UART4, 4)
+
+#define CLK_UART6_PCLK2 CLKSRC(MUX_UART6, 0)
+#define CLK_UART6_PLL4Q CLKSRC(MUX_UART6, 1)
+#define CLK_UART6_HSI CLKSRC(MUX_UART6, 2)
+#define CLK_UART6_CSI CLKSRC(MUX_UART6, 3)
+#define CLK_UART6_HSE CLKSRC(MUX_UART6, 4)
+
+#define CLK_UART78_PCLK1 CLKSRC(MUX_UART78, 0)
+#define CLK_UART78_PLL4Q CLKSRC(MUX_UART78, 1)
+#define CLK_UART78_HSI CLKSRC(MUX_UART78, 2)
+#define CLK_UART78_CSI CLKSRC(MUX_UART78, 3)
+#define CLK_UART78_HSE CLKSRC(MUX_UART78, 4)
+
+#define CLK_LPTIM1_PCLK1 CLKSRC(MUX_LPTIM1, 0)
+#define CLK_LPTIM1_PLL4P CLKSRC(MUX_LPTIM1, 1)
+#define CLK_LPTIM1_PLL3Q CLKSRC(MUX_LPTIM1, 2)
+#define CLK_LPTIM1_LSE CLKSRC(MUX_LPTIM1, 3)
+#define CLK_LPTIM1_LSI CLKSRC(MUX_LPTIM1, 4)
+#define CLK_LPTIM1_CKPER CLKSRC(MUX_LPTIM1, 5)
+
+#define CLK_LPTIM2_PCLK3 CLKSRC(MUX_LPTIM2, 0)
+#define CLK_LPTIM2_PLL4Q CLKSRC(MUX_LPTIM2, 1)
+#define CLK_LPTIM2_CKPER CLKSRC(MUX_LPTIM2, 2)
+#define CLK_LPTIM2_LSE CLKSRC(MUX_LPTIM2, 3)
+#define CLK_LPTIM2_LSI CLKSRC(MUX_LPTIM2, 4)
+
+#define CLK_LPTIM3_PCLK3 CLKSRC(MUX_LPTIM3, 0)
+#define CLK_LPTIM3_PLL4Q CLKSRC(MUX_LPTIM3, 1)
+#define CLK_LPTIM3_CKPER CLKSRC(MUX_LPTIM3, 2)
+#define CLK_LPTIM3_LSE CLKSRC(MUX_LPTIM3, 3)
+#define CLK_LPTIM3_LSI CLKSRC(MUX_LPTIM3, 4)
+
+#define CLK_LPTIM45_PCLK3 CLKSRC(MUX_LPTIM45, 0)
+#define CLK_LPTIM45_PLL4P CLKSRC(MUX_LPTIM45, 1)
+#define CLK_LPTIM45_PLL3Q CLKSRC(MUX_LPTIM45, 2)
+#define CLK_LPTIM45_LSE CLKSRC(MUX_LPTIM45, 3)
+#define CLK_LPTIM45_LSI CLKSRC(MUX_LPTIM45, 4)
+#define CLK_LPTIM45_CKPER CLKSRC(MUX_LPTIM45, 5)
+
+#define CLK_SAI1_PLL4Q CLKSRC(MUX_SAI1, 0)
+#define CLK_SAI1_PLL3Q CLKSRC(MUX_SAI1, 1)
+#define CLK_SAI1_I2SCKIN CLKSRC(MUX_SAI1, 2)
+#define CLK_SAI1_CKPER CLKSRC(MUX_SAI1, 3)
+#define CLK_SAI1_PLL3R CLKSRC(MUX_SAI1, 4)
+
+#define CLK_SAI2_PLL4Q CLKSRC(MUX_SAI2, 0)
+#define CLK_SAI2_PLL3Q CLKSRC(MUX_SAI2, 1)
+#define CLK_SAI2_I2SCKIN CLKSRC(MUX_SAI2, 2)
+#define CLK_SAI2_CKPER CLKSRC(MUX_SAI2, 3)
+#define CLK_SAI2_SPDIF CLKSRC(MUX_SAI2, 4)
+#define CLK_SAI2_PLL3R CLKSRC(MUX_SAI2, 5)
+
+#define CLK_FDCAN_HSE CLKSRC(MUX_FDCAN, 0)
+#define CLK_FDCAN_PLL3Q CLKSRC(MUX_FDCAN, 1)
+#define CLK_FDCAN_PLL4Q CLKSRC(MUX_FDCAN, 2)
+#define CLK_FDCAN_PLL4R CLKSRC(MUX_FDCAN, 3)
+
+#define CLK_SPDIF_PLL4P CLKSRC(MUX_SPDIF, 0)
+#define CLK_SPDIF_PLL3Q CLKSRC(MUX_SPDIF, 1)
+#define CLK_SPDIF_HSI CLKSRC(MUX_SPDIF, 2)
+
+#define CLK_ADC1_PLL4R CLKSRC(MUX_ADC1, 0)
+#define CLK_ADC1_CKPER CLKSRC(MUX_ADC1, 1)
+#define CLK_ADC1_PLL3Q CLKSRC(MUX_ADC1, 2)
+
+#define CLK_ADC2_PLL4R CLKSRC(MUX_ADC2, 0)
+#define CLK_ADC2_CKPER CLKSRC(MUX_ADC2, 1)
+#define CLK_ADC2_PLL3Q CLKSRC(MUX_ADC2, 2)
+
+#define CLK_SDMMC1_HCLK6 CLKSRC(MUX_SDMMC1, 0)
+#define CLK_SDMMC1_PLL3R CLKSRC(MUX_SDMMC1, 1)
+#define CLK_SDMMC1_PLL4P CLKSRC(MUX_SDMMC1, 2)
+#define CLK_SDMMC1_HSI CLKSRC(MUX_SDMMC1, 3)
+
+#define CLK_SDMMC2_HCLK6 CLKSRC(MUX_SDMMC2, 0)
+#define CLK_SDMMC2_PLL3R CLKSRC(MUX_SDMMC2, 1)
+#define CLK_SDMMC2_PLL4P CLKSRC(MUX_SDMMC2, 2)
+#define CLK_SDMMC2_HSI CLKSRC(MUX_SDMMC2, 3)
+
+#define CLK_ETH1_PLL4P CLKSRC(MUX_ETH1, 0)
+#define CLK_ETH1_PLL3Q CLKSRC(MUX_ETH1, 1)
+
+#define CLK_ETH2_PLL4P CLKSRC(MUX_ETH2, 0)
+#define CLK_ETH2_PLL3Q CLKSRC(MUX_ETH2, 1)
+
+#define CLK_USBPHY_HSE CLKSRC(MUX_USBPHY, 0)
+#define CLK_USBPHY_PLL4R CLKSRC(MUX_USBPHY, 1)
+#define CLK_USBPHY_HSE_DIV2 CLKSRC(MUX_USBPHY, 2)
+
+#define CLK_USBO_PLL4R CLKSRC(MUX_USBO, 0)
+#define CLK_USBO_USBPHY CLKSRC(MUX_USBO, 1)
+
+#define CLK_QSPI_ACLK CLKSRC(MUX_QSPI, 0)
+#define CLK_QSPI_PLL3R CLKSRC(MUX_QSPI, 1)
+#define CLK_QSPI_PLL4P CLKSRC(MUX_QSPI, 2)
+#define CLK_QSPI_CKPER CLKSRC(MUX_QSPI, 3)
+
+#define CLK_FMC_ACLK CLKSRC(MUX_FMC, 0)
+#define CLK_FMC_PLL3R CLKSRC(MUX_FMC, 1)
+#define CLK_FMC_PLL4P CLKSRC(MUX_FMC, 2)
+#define CLK_FMC_CKPER CLKSRC(MUX_FMC, 3)
+
+#define CLK_RNG1_CSI CLKSRC(MUX_RNG1, 0)
+#define CLK_RNG1_PLL4R CLKSRC(MUX_RNG1, 1)
+/* WARNING: POSITION 2 OF RNG1 MUX IS RESERVED */
+#define CLK_RNG1_LSI CLKSRC(MUX_RNG1, 3)
+
+#define CLK_STGEN_HSI CLKSRC(MUX_STGEN, 0)
+#define CLK_STGEN_HSE CLKSRC(MUX_STGEN, 1)
+
+#define CLK_DCMIPP_ACLK CLKSRC(MUX_DCMIPP, 0)
+#define CLK_DCMIPP_PLL2Q CLKSRC(MUX_DCMIPP, 1)
+#define CLK_DCMIPP_PLL4P CLKSRC(MUX_DCMIPP, 2)
+#define CLK_DCMIPP_CKPER CLKSRC(MUX_DCMIPP, 3)
+
+#define CLK_SAES_AXI CLKSRC(MUX_SAES, 0)
+#define CLK_SAES_CKPER CLKSRC(MUX_SAES, 1)
+#define CLK_SAES_PLL4R CLKSRC(MUX_SAES, 2)
+#define CLK_SAES_LSI CLKSRC(MUX_SAES, 3)
+
+/* PLL output is enable when x=1, with x=p,q or r */
+#define PQR(p, q, r) (((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2))
+
+/* define for st,pll /csg */
+#define SSCG_MODE_CENTER_SPREAD 0
+#define SSCG_MODE_DOWN_SPREAD 1
+
+/* define for st,drive */
+#define LSEDRV_LOWEST 0
+#define LSEDRV_MEDIUM_LOW 1
+#define LSEDRV_MEDIUM_HIGH 2
+#define LSEDRV_HIGHEST 3
+
+#endif
--
2.47.2
More information about the U-Boot
mailing list