Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stm32f412 and stm32f413 have a 48MHz clock for SDMMC or USB #82259

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions drivers/clock_control/clock_stm32_ll_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ int enabled_clock(uint32_t src_clk)
}
break;
#endif /* STM32_SRC_PLL_R */
#if defined(STM32_SRC_PLLI2S_Q)
case STM32_SRC_PLLI2S_Q:
if (!IS_ENABLED(STM32_PLLI2S_Q_ENABLED)) {
r = -ENOTSUP;
}
break;
#endif /* STM32_SRC_PLLI2S_Q */
#if defined(STM32_SRC_PLLI2S_R)
case STM32_SRC_PLLI2S_R:
if (!IS_ENABLED(STM32_PLLI2S_R_ENABLED)) {
Expand Down Expand Up @@ -426,6 +433,14 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
STM32_PLL_R_DIVISOR);
break;
#endif
#if defined(STM32_SRC_PLLI2S_Q) & STM32_PLLI2S_ENABLED
case STM32_SRC_PLLI2S_Q:
*rate = get_pll_div_frequency(get_pllsrc_frequency(),
STM32_PLLI2S_M_DIVISOR,
STM32_PLLI2S_N_MULTIPLIER,
STM32_PLLI2S_Q_DIVISOR);
break;
#endif /* STM32_SRC_PLLI2S_Q */
#if defined(STM32_SRC_PLLI2S_R) & STM32_PLLI2S_ENABLED
case STM32_SRC_PLLI2S_R:
*rate = get_pll_div_frequency(get_pllsrc_frequency(),
Expand All @@ -434,6 +449,7 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
STM32_PLLI2S_R_DIVISOR);
break;
#endif /* STM32_SRC_PLLI2S_R */

/* PLLSAI1x not supported yet */
/* PLLSAI2x not supported yet */
#if defined(STM32_SRC_LSE)
Expand Down Expand Up @@ -466,6 +482,12 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
*rate = STM32_HSI48_FREQ;
break;
#endif /* STM32_HSI48_ENABLED */
#if defined(STM32_CK48_ENABLED)
case STM32_SRC_CK48:
*rate = get_ck48_frequency();
break;
#endif /* STM32_CK48_ENABLED */

default:
return -ENOTSUP;
}
Expand Down
7 changes: 7 additions & 0 deletions drivers/clock_control/clock_stm32_ll_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
#define z_plli2s_m(v) LL_RCC_PLLI2SM_DIV_ ## v
#define plli2sm(v) z_plli2s_m(v)

#define z_plli2s_q(v) LL_RCC_PLLI2SQ_DIV_ ## v
#define plli2sq(v) z_plli2s_q(v)

#define z_plli2s_r(v) LL_RCC_PLLI2SR_DIV_ ## v
#define plli2sr(v) z_plli2s_r(v)

Expand All @@ -52,6 +55,10 @@ void config_enable_default_clocks(void);
void config_regulator_voltage(uint32_t hclk_freq);
int enabled_clock(uint32_t src_clk);

#if defined(STM32_CK48_ENABLED)
uint32_t get_ck48_frequency(void);
#endif

/* functions exported to the soc power.c */
int stm32_clock_control_init(const struct device *dev);
void stm32_clock_control_standby_exit(void);
Expand Down
49 changes: 49 additions & 0 deletions drivers/clock_control/clock_stm32f2_f4_f7.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,46 @@ uint32_t get_pllsrc_frequency(void)
return 0;
}

#if defined(STM32_CK48_ENABLED)
/**
* @brief calculate the CK48 frequency depending on its clock source
*/
__unused
uint32_t get_ck48_frequency(void)
{
uint32_t source;

if (LL_RCC_GetCK48MClockSource(LL_RCC_CK48M_CLKSOURCE) ==
LL_RCC_CK48M_CLKSOURCE_PLL) {
/* Get the PLL48CK source : HSE or HSI */
source = (LL_RCC_PLL_GetMainSource() == LL_RCC_PLLSOURCE_HSE)
? HSE_VALUE
: HSI_VALUE;
/* Get the PLL48CK Q freq. No HAL macro for that */
return __LL_RCC_CALC_PLLCLK_48M_FREQ(source,
LL_RCC_PLL_GetDivider(),
LL_RCC_PLL_GetN(),
LL_RCC_PLL_GetQ()
);
} else if (LL_RCC_GetCK48MClockSource(LL_RCC_CK48M_CLKSOURCE) ==
LL_RCC_CK48M_CLKSOURCE_PLLI2S) {
/* Get the PLL I2S source : HSE or HSI */
source = (LL_RCC_PLLI2S_GetMainSource() == LL_RCC_PLLSOURCE_HSE)
? HSE_VALUE
: HSI_VALUE;
/* Get the PLL I2S Q freq. No HAL macro for that */
return __LL_RCC_CALC_PLLI2S_48M_FREQ(source,
LL_RCC_PLLI2S_GetDivider(),
LL_RCC_PLLI2S_GetN(),
LL_RCC_PLLI2S_GetQ()
);
}

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

/**
* @brief Set up pll configuration
*/
Expand Down Expand Up @@ -114,7 +154,16 @@ void config_plli2s(void)
plli2sm(STM32_PLLI2S_M_DIVISOR),
STM32_PLLI2S_N_MULTIPLIER,
plli2sr(STM32_PLLI2S_R_DIVISOR));
#if STM32_PLLI2S_Q_ENABLED
/* There is a Q divider on the PLLI2S to configure the PLL48CK */
LL_RCC_PLLI2S_ConfigDomain_48M(get_pll_source(),
plli2sm(STM32_PLLI2S_M_DIVISOR),
STM32_PLLI2S_N_MULTIPLIER,
plli2sq(STM32_PLLI2S_Q_DIVISOR));
#endif /* STM32_PLLI2S_Q_ENABLED */
Comment on lines +157 to +163
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is currently no configuration of main PLL Q channel. You should also add the LL_RCC_PLL_ConfigDomain_48M function in the config_pll_sysclock function.

#endif


}

#endif /* STM32_PLLI2S_ENABLED */
Expand Down
9 changes: 7 additions & 2 deletions dts/arm/st/f4/stm32f412.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
compatible = "st,stm32f412-plli2s-clock";
status = "disabled";
};

clk48: clk48 {
#clock-cells = <0>;
compatible = "st,stm32-clock-mux";
status = "disabled";
};
};

soc {
Expand Down Expand Up @@ -201,8 +207,7 @@
};

sdmmc1: sdmmc@40012c00 {
clocks = <&rcc STM32_CLOCK(APB2, 11U)>,
<&rcc STM32_SRC_SYSCLK SDIO_SEL(1)>;
clocks = <&rcc STM32_CLOCK(APB2, 11U)>;
};

quadspi: quadspi@a0001000 {
Expand Down
20 changes: 20 additions & 0 deletions dts/bindings/clock/st,stm32f412-plli2s-clock.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,23 @@ properties:
description: |
Division factor for the PLL input clock
Valid range: 2 - 63

div-q:
type: int
description: |
PLLI2S division factor for I2S Clocks to supply USB/SDIO/RNG
enum:
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
9 changes: 9 additions & 0 deletions include/zephyr/drivers/clock_control/stm32_clock_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#elif defined(CONFIG_SOC_SERIES_STM32F2X) || \
defined(CONFIG_SOC_SERIES_STM32F4X)
#include <zephyr/dt-bindings/clock/stm32f4_clock.h>
#include <zephyr/dt-bindings/clock/stm32f410_clock.h>
#elif defined(CONFIG_SOC_SERIES_STM32F7X)
#include <zephyr/dt-bindings/clock/stm32f7_clock.h>
#elif defined(CONFIG_SOC_SERIES_STM32G0X)
Expand Down Expand Up @@ -183,6 +184,8 @@
#define STM32_PLLI2S_ENABLED 1
#define STM32_PLLI2S_M_DIVISOR DT_PROP(DT_NODELABEL(plli2s), div_m)
#define STM32_PLLI2S_N_MULTIPLIER DT_PROP(DT_NODELABEL(plli2s), mul_n)
#define STM32_PLLI2S_Q_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(plli2s), div_q)
#define STM32_PLLI2S_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(plli2s), div_q, 1)
#define STM32_PLLI2S_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(plli2s), div_r)
#define STM32_PLLI2S_R_DIVISOR DT_PROP_OR(DT_NODELABEL(plli2s), div_r, 1)
#endif
Expand Down Expand Up @@ -428,6 +431,12 @@
#define STM32_CKPER_ENABLED 1
#endif

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk48), st_stm32_clock_mux, okay)
/* Assuming the 48MHz clock is 48MHz */
#define STM32_CK48_ENABLED 1
#define STM32_CK48_FREQ 48000000
gautierg-st marked this conversation as resolved.
Show resolved Hide resolved
#endif

/** Driver structure definition */

struct stm32_pclken {
Expand Down
16 changes: 10 additions & 6 deletions include/zephyr/dt-bindings/clock/stm32f4_clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,18 @@
/* defined in stm32_common_clocks.h */
/** Fixed clocks */
/* Low speed clocks defined in stm32_common_clocks.h */
#define STM32_SRC_HSI (STM32_SRC_LSI + 1)
#define STM32_SRC_HSE (STM32_SRC_HSI + 1)
#define STM32_SRC_HSI (STM32_SRC_LSI + 1)
#define STM32_SRC_HSE (STM32_SRC_HSI + 1)
/** PLL clock outputs */
#define STM32_SRC_PLL_P (STM32_SRC_HSE + 1)
#define STM32_SRC_PLL_Q (STM32_SRC_PLL_P + 1)
#define STM32_SRC_PLL_R (STM32_SRC_PLL_Q + 1)
#define STM32_SRC_PLL_P (STM32_SRC_HSE + 1)
#define STM32_SRC_PLL_Q (STM32_SRC_PLL_P + 1)
#define STM32_SRC_PLL_R (STM32_SRC_PLL_Q + 1)
/** I2S sources */
#define STM32_SRC_PLLI2S_R (STM32_SRC_PLL_R + 1)
#define STM32_SRC_PLLI2S_Q (STM32_SRC_PLL_R + 1)
#define STM32_SRC_PLLI2S_R (STM32_SRC_PLLI2S_Q + 1)
/* CLK48MHz sources */
#define STM32_SRC_CK48 (STM32_SRC_PLLI2S_R + 1)

/* I2S_CKIN not supported yet */
/* #define STM32_SRC_I2S_CKIN TBD */

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2024 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*/

/* Node is disabled by default unless the PLL_I2S is enabled */
&clk48 {
/* select one source for the clk48MHz domain clock */
/* clocks = <&rcc STM32_SRC_PLL_Q CK48M_SEL(0)>;*/
clocks = <&rcc STM32_SRC_PLLI2S_Q CK48M_SEL(1)>;
status = "okay";
};

&plli2s {
div-m = <4>;
mul-n = <96>;
div-q = <4>;
div-r = <2>;
clocks = <&clk_hse>;
status = "okay";
};

&sdmmc1 {
clocks = <&rcc STM32_CLOCK(APB2, 11U)>,
/* select one source for the sdmmc domain clock */
/* <&rcc STM32_SRC_SYSCLK SDIO_SEL(1)>; */
<&rcc STM32_SRC_CK48 SDIO_SEL(0)>;
pinctrl-0 = <&sdio_cmd_pa6 &sdio_ck_pc12
&sdio_d0_pc8 &sdio_d1_pc9
&sdio_d2_pc10 &sdio_d3_pc11>;
pinctrl-names = "default";
status = "okay";
};
Loading
Loading