[U-Boot] [PATCH 2/6] clk: stm32: retrieve external oscillator frequency from DT

patrice.chotard at st.com patrice.chotard at st.com
Thu Jan 18 12:39:30 UTC 2018


From: Patrice Chotard <patrice.chotard at st.com>

All current STM32F4 supported boards uses a 8MHz external oscillator.
All current STM32F7 supported boards uses a 25MHz external oscillator.

In order to introduce the new stm32f429-evaluation board which uses a
25MHz external oscillator without creating a dedicated struct
stm32_clk_info for this board, retrieve the external oscillator
frequency from DT and set pll_m accordingly to obtain 1MHz for the VCO.

Signed-off-by: Patrice Chotard <patrice.chotard at st.com>
---
 drivers/clk/clk_stm32f.c | 78 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 57 insertions(+), 21 deletions(-)

diff --git a/drivers/clk/clk_stm32f.c b/drivers/clk/clk_stm32f.c
index 63116e0..ebe1ce6 100644
--- a/drivers/clk/clk_stm32f.c
+++ b/drivers/clk/clk_stm32f.c
@@ -93,10 +93,9 @@ enum periph_clock {
 	STMMAC_CLOCK_CFG,
 };
 
-struct stm32_clk_info stm32f4_clk_info = {
+static const struct stm32_clk_info stm32f4_clk_info = {
 	/* 180 MHz */
 	.sys_pll_psc = {
-		.pll_m = 8,
 		.pll_n = 360,
 		.pll_p = 2,
 		.pll_q = 8,
@@ -108,10 +107,9 @@ struct stm32_clk_info stm32f4_clk_info = {
 	.v2 = false,
 };
 
-struct stm32_clk_info stm32f7_clk_info = {
+static const struct stm32_clk_info stm32f7_clk_info = {
 	/* 200 MHz */
 	.sys_pll_psc = {
-		.pll_m = 25,
 		.pll_n = 400,
 		.pll_p = 2,
 		.pll_q = 8,
@@ -126,7 +124,8 @@ struct stm32_clk_info stm32f7_clk_info = {
 struct stm32_clk {
 	struct stm32_rcc_regs *base;
 	struct stm32_pwr_regs *pwr_regs;
-	struct stm32_clk_info *info;
+	struct stm32_clk_info info;
+	unsigned long hse_rate;
 };
 
 static int configure_clocks(struct udevice *dev)
@@ -134,7 +133,7 @@ static int configure_clocks(struct udevice *dev)
 	struct stm32_clk *priv = dev_get_priv(dev);
 	struct stm32_rcc_regs *regs = priv->base;
 	struct stm32_pwr_regs *pwr = priv->pwr_regs;
-	struct pll_psc sys_pll_psc = priv->info->sys_pll_psc;
+	struct pll_psc *sys_pll_psc = &priv->info.sys_pll_psc;
 	u32 pllsaicfgr = 0;
 
 	/* Reset RCC configuration */
@@ -152,20 +151,20 @@ static int configure_clocks(struct udevice *dev)
 		;
 
 	setbits_le32(&regs->cfgr, ((
-		sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT)
-		| (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT)
-		| (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
+		sys_pll_psc->ahb_psc << RCC_CFGR_HPRE_SHIFT)
+		| (sys_pll_psc->apb1_psc << RCC_CFGR_PPRE1_SHIFT)
+		| (sys_pll_psc->apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
 
 	/* Configure the main PLL */
 	setbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */
 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLM_MASK,
-			sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT);
+			sys_pll_psc->pll_m << RCC_PLLCFGR_PLLM_SHIFT);
 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLN_MASK,
-			sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT);
+			sys_pll_psc->pll_n << RCC_PLLCFGR_PLLN_SHIFT);
 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLP_MASK,
-			((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
+			((sys_pll_psc->pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLQ_MASK,
-			sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT);
+			sys_pll_psc->pll_q << RCC_PLLCFGR_PLLQ_SHIFT);
 
 	/* Configure the SAI PLL to get a 48 MHz source */
 	pllsaicfgr = RCC_PLLSAICFGR_PLLSAIR_2 | RCC_PLLSAICFGR_PLLSAIQ_4 |
@@ -178,7 +177,7 @@ static int configure_clocks(struct udevice *dev)
 	while (!(readl(&regs->cr) & RCC_CR_PLLRDY))
 		;
 
-	if (priv->info->v2) { /*stm32f7 case */
+	if (priv->info.v2) { /*stm32f7 case */
 		/* select PLLSAI as 48MHz clock source */
 		setbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
 
@@ -202,7 +201,7 @@ static int configure_clocks(struct udevice *dev)
 
 	setbits_le32(&regs->apb1enr, RCC_APB1ENR_PWREN);
 
-	if (priv->info->has_overdrive) {
+	if (priv->info.has_overdrive) {
 		/*
 		 * Enable high performance mode
 		 * System frequency up to 200 MHz
@@ -241,7 +240,7 @@ static unsigned long stm32_clk_pll48clk_rate(struct stm32_clk *priv,
 	pllq = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLQ_MASK)
 	       >> RCC_PLLCFGR_PLLQ_SHIFT;
 
-	if (priv->info->v2) /*stm32f7 case */
+	if (priv->info.v2) /*stm32f7 case */
 		pllsai = readl(&regs->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL;
 	else
 		pllsai = readl(&regs->dckcfgr) & RCC_DCKCFGRX_CK48MSEL;
@@ -253,7 +252,7 @@ static unsigned long stm32_clk_pll48clk_rate(struct stm32_clk *priv,
 			>> RCC_PLLSAICFGR_PLLSAIN_SHIFT);
 		pllsaip = ((((readl(&regs->pllsaicfgr) & RCC_PLLCFGR_PLLSAIP_MASK)
 			>> RCC_PLLSAICFGR_PLLSAIP_SHIFT) + 1) << 1);
-		return ((CONFIG_STM32_HSE_HZ / pllm) * pllsain) / pllsaip;
+		return ((priv->hse_rate / pllm) * pllsain) / pllsaip;
 	}
 	/* PLL48CLK is selected from PLLQ */
 	return sysclk / pllq;
@@ -281,7 +280,7 @@ static unsigned long stm32_clk_get_rate(struct clk *clk)
 			>> RCC_PLLCFGR_PLLN_SHIFT);
 		pllp = ((((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
 			>> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
-		sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp;
+		sysclk = ((priv->hse_rate / pllm) * plln) / pllp;
 	} else {
 		return -EINVAL;
 	}
@@ -372,6 +371,8 @@ void clock_setup(int peripheral)
 static int stm32_clk_probe(struct udevice *dev)
 {
 	struct ofnode_phandle_args args;
+	struct udevice *fixed_clock_dev = NULL;
+	struct clk clk;
 	int err;
 
 	debug("%s\n", __func__);
@@ -387,16 +388,51 @@ static int stm32_clk_probe(struct udevice *dev)
 
 	switch (dev_get_driver_data(dev)) {
 	case STM32F4:
-		priv->info = &stm32f4_clk_info;
+		memcpy(&priv->info, &stm32f4_clk_info,
+		       sizeof(struct stm32_clk_info));
 		break;
 	case STM32F7:
-		priv->info = &stm32f7_clk_info;
+		memcpy(&priv->info, &stm32f7_clk_info,
+		       sizeof(struct stm32_clk_info));
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	if (priv->info->has_overdrive) {
+	/* retrieve HSE frequency (external oscillator) */
+	err = uclass_get_device_by_name(UCLASS_CLK, "clk-hse",
+					&fixed_clock_dev);
+
+	if (err) {
+		pr_err("Can't find fixed clock (%d)", err);
+		return err;
+	}
+
+	err = clk_request(fixed_clock_dev, &clk);
+	if (err) {
+		pr_err("Can't request %s clk (%d)", fixed_clock_dev->name,
+		       err);
+		return err;
+	}
+
+	/*
+	 * set pllm factor accordingly to the external oscillator
+	 * frequency (HSE). For STM32F4 and STM32F7, we want VCO
+	 * freq at 1MHz
+	 * if input PLL frequency is 25Mhz, divide it by 25
+	 */
+	clk.id = 0;
+	priv->hse_rate = clk_get_rate(&clk);
+
+	if (priv->hse_rate < 1000000) {
+		pr_err("%s: unexpected HSE clock rate = %ld \"n", __func__,
+		       priv->hse_rate);
+		return -EINVAL;
+	}
+
+	priv->info.sys_pll_psc.pll_m = priv->hse_rate / 1000000;
+
+	if (priv->info.has_overdrive) {
 		err = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0,
 						 &args);
 		if (err) {
-- 
1.9.1



More information about the U-Boot mailing list