Commit 0abbc2f0 authored by Alain Volmat's avatar Alain Volmat Committed by Benjamin Cabé
Browse files

drivers: clock: stm32: add PLLSAI1 support (common + L4)



Add stm32 common clock handling for the SAI1 PLL.

Signed-off-by: default avatarAlain Volmat <alain.volmat@foss.st.com>
parent f5ff9fd0
Loading
Loading
Loading
Loading
+55 −1
Original line number Diff line number Diff line
@@ -228,6 +228,27 @@ int enabled_clock(uint32_t src_clk)
		}
		break;
#endif /* STM32_SRC_PLLI2S_R */
#if defined(STM32_SRC_PLLSAI1_P)
	case STM32_SRC_PLLSAI1_P:
		if (!IS_ENABLED(STM32_PLLSAI1_P_ENABLED)) {
			r = -ENOTSUP;
		}
		break;
#endif /* STM32_SRC_PLLSAI1_P */
#if defined(STM32_SRC_PLLSAI1_Q)
	case STM32_SRC_PLLSAI1_Q:
		if (!IS_ENABLED(STM32_PLLSAI1_Q_ENABLED)) {
			r = -ENOTSUP;
		}
		break;
#endif /* STM32_SRC_PLLSAI1_Q */
#if defined(STM32_SRC_PLLSAI1_R)
	case STM32_SRC_PLLSAI1_R:
		if (!IS_ENABLED(STM32_PLLSAI1_R_ENABLED)) {
			r = -ENOTSUP;
		}
		break;
#endif /* STM32_SRC_PLLSAI1_R */
#if defined(STM32_SRC_PLL2CLK)
	case STM32_SRC_PLL2CLK:
		if (!IS_ENABLED(STM32_PLL2_ENABLED)) {
@@ -441,8 +462,31 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
					      STM32_PLLI2S_R_DIVISOR);
		break;
#endif /* STM32_SRC_PLLI2S_R */
#if defined(STM32_SRC_PLLSAI1_P) & STM32_PLLSAI1_P_ENABLED
	case STM32_SRC_PLLSAI1_P:
		*rate = get_pll_div_frequency(get_pllsai1src_frequency(),
					      STM32_PLLSAI1_M_DIVISOR,
					      STM32_PLLSAI1_N_MULTIPLIER,
					      STM32_PLLSAI1_P_DIVISOR);
		break;
#endif /* STM32_SRC_PLLSAI1_P */
#if defined(STM32_SRC_PLLSAI1_Q) & STM32_PLLSAI1_Q_ENABLED
	case STM32_SRC_PLLSAI1_Q:
		*rate = get_pll_div_frequency(get_pllsai1src_frequency(),
					      STM32_PLLSAI1_M_DIVISOR,
					      STM32_PLLSAI1_N_MULTIPLIER,
					      STM32_PLLSAI1_Q_DIVISOR);
		break;
#endif /* STM32_SRC_PLLSAI1_Q */
#if defined(STM32_SRC_PLLSAI1_R) & STM32_PLLSAI1_R_ENABLED
	case STM32_SRC_PLLSAI1_R:
		*rate = get_pll_div_frequency(get_pllsai1src_frequency(),
					      STM32_PLLSAI1_M_DIVISOR,
					      STM32_PLLSAI1_N_MULTIPLIER,
					      STM32_PLLSAI1_R_DIVISOR);
		break;
#endif /* STM32_SRC_PLLSAI1_R */

/* PLLSAI1x not supported yet */
/* PLLSAI2x not supported yet */
#if defined(STM32_SRC_LSE)
	case STM32_SRC_LSE:
@@ -624,6 +668,16 @@ static void set_up_plls(void)
		/* Wait for PLL ready */
	}
#endif /* STM32_PLLI2S_ENABLED */

#if defined(STM32_PLLSAI1_ENABLED)
	config_pllsai1();

	/* Enable PLL */
	LL_RCC_PLLSAI1_Enable();
	while (LL_RCC_PLLSAI1_IsReady() != 1U) {
		/* Wait for PLL ready */
	}
#endif /* STM32_PLLSAI1_ENABLED */
}

static void set_up_fixed_clock_sources(void)
+20 −0
Original line number Diff line number Diff line
@@ -42,6 +42,22 @@
#define z_plli2s_r(v) LL_RCC_PLLI2SR_DIV_ ## v
#define plli2sr(v) z_plli2s_r(v)

#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
#define z_pllsai1_m(v) LL_RCC_PLLSAI1M_DIV_ ## v
#else
#define z_pllsai1_m(v) LL_RCC_PLLM_DIV_ ## v
#endif
#define pllsai1m(v) z_pllsai1_m(v)

#define z_pllsai1_p(v) LL_RCC_PLLSAI1P_DIV_ ## v
#define pllsai1p(v) z_pllsai1_p(v)

#define z_pllsai1_q(v) LL_RCC_PLLSAI1Q_DIV_ ## v
#define pllsai1q(v) z_pllsai1_q(v)

#define z_pllsai1_r(v) LL_RCC_PLLSAI1R_DIV_ ## v
#define pllsai1r(v) z_pllsai1_r(v)

#ifdef __cplusplus
extern "C" {
#endif
@@ -57,6 +73,10 @@ void config_pll2(void);
#if defined(STM32_PLLI2S_ENABLED)
void config_plli2s(void);
#endif
#if defined(STM32_PLLSAI1_ENABLED)
uint32_t get_pllsai1src_frequency(void);
void config_pllsai1(void);
#endif
void config_enable_default_clocks(void);
void config_regulator_voltage(uint32_t hclk_freq);
int enabled_clock(uint32_t src_clk);
+93 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
#include <zephyr/sys/time_units.h>
#include "clock_stm32_ll_common.h"

#if defined(STM32_PLL_ENABLED)
#if defined(STM32_PLL_ENABLED) || defined(STM32_PLLSAI1_ENABLED)

#if defined(LL_RCC_MSIRANGESEL_RUN)
#define CALC_RUN_MSI_FREQ(range) __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGESEL_RUN, \
@@ -26,6 +26,9 @@
#define CALC_RUN_MSI_FREQ(range) __LL_RCC_CALC_MSI_FREQ(range << RCC_CR_MSIRANGE_Pos);
#endif

#endif

#if defined(STM32_PLL_ENABLED)
/**
 * @brief Return PLL source
 */
@@ -87,6 +90,95 @@ void config_pll_sysclock(void)

#endif /* defined(STM32_PLL_ENABLED) */

#if defined(STM32_PLLSAI1_ENABLED)

/**
 * @brief Return PLLSAI1 source
 */
__unused
static uint32_t get_pllsai1_source(void)
{
	/* Configure PLL source */
	if (IS_ENABLED(STM32_PLLSAI1_SRC_HSI)) {
		return LL_RCC_PLLSOURCE_HSI;
	} else if (IS_ENABLED(STM32_PLLSAI1_SRC_HSE)) {
		return LL_RCC_PLLSOURCE_HSE;
	} else if (IS_ENABLED(STM32_PLLSAI1_SRC_MSI)) {
		return LL_RCC_PLLSOURCE_MSI;
	}

	__ASSERT(0, "Invalid source");
	return 0;
}

/**
 * @brief Get the PLLSAI1 source frequency
 */
__unused
uint32_t get_pllsai1src_frequency(void)
{
	if (IS_ENABLED(STM32_PLLSAI1_SRC_HSI)) {
		return STM32_HSI_FREQ;
	} else if (IS_ENABLED(STM32_PLLSAI1_SRC_HSE)) {
		return STM32_HSE_FREQ;
#if defined(STM32_MSI_ENABLED)
	} else if (IS_ENABLED(STM32_PLLSAI1_SRC_MSI)) {
		return CALC_RUN_MSI_FREQ(STM32_MSI_RANGE);
#endif
	}

	__ASSERT(0, "Invalid source");
	return 0;
}

/**
 * @brief Set up PLLSAI1 configuration
 */
__unused
void config_pllsai1(void)
{
#ifndef RCC_PLLSAI1M_DIV_1_16_SUPPORT
	/*
	 * On some L4 series, there is no dedicated M_DIVISOR for PLLSAIs
	 * and it is shared with PLL and other PLLSAIs. Ensure that if they
	 * exist, they have the same value
	 */
#if defined(STM32_PLL_M_DIVISOR) && (STM32_PLL_M_DIVISOR != STM32_PLLSAI1_M_DIVISOR)
#error "PLLSAI1 M divisor must have same value as PLL M divisor"
#elif defined(STM32_PLLSAI2_M_DIVISOR) && (STM32_PLLSAI2_M_DIVISOR != STM32_PLLSAI1_M_DIVISOR)
#error "PLLSAI1 M divisor must have same value as PLLSAI2 M divisor"
#endif
#endif
#if STM32_PLLSAI1_P_ENABLED
	LL_RCC_PLLSAI1_ConfigDomain_SAI(get_pllsai1_source(),
					pllsai1m(STM32_PLLSAI1_M_DIVISOR),
					STM32_PLLSAI1_N_MULTIPLIER,
					pllsai1p(STM32_PLLSAI1_P_DIVISOR));

	LL_RCC_PLLSAI1_EnableDomain_SAI();
#endif /* STM32_PLLSAI1_P_ENABLED */

#if STM32_PLLSAI1_Q_ENABLED
	LL_RCC_PLLSAI1_ConfigDomain_48M(get_pllsai1_source(),
					pllsai1m(STM32_PLLSAI1_M_DIVISOR),
					STM32_PLLSAI1_N_MULTIPLIER,
					pllsai1q(STM32_PLLSAI1_Q_DIVISOR));

	LL_RCC_PLLSAI1_EnableDomain_48M();
#endif /* STM32_PLLSAI1_Q_ENABLED */

#if STM32_PLLSAI1_R_ENABLED
	LL_RCC_PLLSAI1_ConfigDomain_ADC(get_pllsai1_source(),
					pllsai1m(STM32_PLLSAI1_M_DIVISOR),
					STM32_PLLSAI1_N_MULTIPLIER,
					pllsai1r(STM32_PLLSAI1_R_DIVISOR));

	LL_RCC_PLLSAI1_EnableDomain_ADC();
#endif /* STM32_PLLSAI1_R_ENABLED */
}

#endif /* STM32_PLLSAI1_ENABLED */

/**
 * @brief Activate default clocks
 */
+34 −0
Original line number Diff line number Diff line
@@ -218,6 +218,18 @@
#define STM32_PLLI2S_R_DIVISOR		DT_PROP_OR(DT_NODELABEL(plli2s), div_r, 1)
#endif

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai1), st_stm32l4_pllsai_clock, okay)
#define STM32_PLLSAI1_ENABLED	1
#define STM32_PLLSAI1_M_DIVISOR		DT_PROP(DT_NODELABEL(pllsai1), div_m)
#define STM32_PLLSAI1_N_MULTIPLIER	DT_PROP(DT_NODELABEL(pllsai1), mul_n)
#define STM32_PLLSAI1_P_ENABLED		DT_NODE_HAS_PROP(DT_NODELABEL(pllsai1), div_p)
#define STM32_PLLSAI1_P_DIVISOR		DT_PROP_OR(DT_NODELABEL(pllsai1), div_p, 1)
#define STM32_PLLSAI1_Q_ENABLED		DT_NODE_HAS_PROP(DT_NODELABEL(pllsai1), div_q)
#define STM32_PLLSAI1_Q_DIVISOR		DT_PROP_OR(DT_NODELABEL(pllsai1), div_q, 1)
#define STM32_PLLSAI1_R_ENABLED		DT_NODE_HAS_PROP(DT_NODELABEL(pllsai1), div_r)
#define STM32_PLLSAI1_R_DIVISOR		DT_PROP_OR(DT_NODELABEL(pllsai1), div_r, 1)
#endif

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32u5_pll_clock, okay) || \
	DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7_pll_clock, okay) || \
	DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7rs_pll_clock, okay) || \
@@ -407,6 +419,28 @@

#endif

/** PLLSAI1 clock source */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pllsai1), okay) && \
	DT_NODE_HAS_PROP(DT_NODELABEL(pllsai1), clocks)
#define DT_PLLSAI1_CLOCKS_CTRL	DT_CLOCKS_CTLR(DT_NODELABEL(pllsai1))
#if DT_SAME_NODE(DT_PLLSAI1_CLOCKS_CTRL, DT_NODELABEL(clk_msi))
#define STM32_PLLSAI1_SRC_MSI	1
#endif
#if DT_SAME_NODE(DT_PLLSAI1_CLOCKS_CTRL, DT_NODELABEL(clk_hsi))
#define STM32_PLLSAI1_SRC_HSI	1
#endif
#if DT_SAME_NODE(DT_PLLSAI1_CLOCKS_CTRL, DT_NODELABEL(clk_hse))
#define STM32_PLLSAI1_SRC_HSE	1
#endif

#endif

/* On STM32L4 series - PLL / PLLSAI1 shared same source */
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32l4_pll_clock, okay) && \
	DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai1), st_stm32l4_pllsai_clock, okay) && \
	!DT_SAME_NODE(DT_PLL_CLOCKS_CTRL, DT_PLLSAI1_CLOCKS_CTRL)
#error "On STM32L4 series, PLL / PLLSAI1 must have the same source"
#endif

/** Fixed clocks related symbols */

+4 −1
Original line number Diff line number Diff line
@@ -35,7 +35,10 @@
#define STM32_SRC_PLL_P		(STM32_SRC_PCLK + 1)
#define STM32_SRC_PLL_Q		(STM32_SRC_PLL_P + 1)
#define STM32_SRC_PLL_R		(STM32_SRC_PLL_Q + 1)
/* TODO: PLLSAI clocks */
/* PLLSAI1 clocks */
#define STM32_SRC_PLLSAI1_P	(STM32_SRC_PLL_R + 1)
#define STM32_SRC_PLLSAI1_Q	(STM32_SRC_PLLSAI1_P + 1)
#define STM32_SRC_PLLSAI1_R	(STM32_SRC_PLLSAI1_Q + 1)

/** @brief RCC_CCIPR register offset */
#define CCIPR_REG		0x88