refactor(st-clock): improve DT parsing for PLL nodes
Add a function to get PLL settings from DT:
"cfg" property is mandatory, an error is generated if not found.
"frac" is optional, default value is returned if not found.
"csg" is optional too, a boolean value indicates if it has been
found, and its value is updated.
Store each PLL node validity information, this avoids parsing DT
several times.
Change-Id: I039466fbe1e67d160f7112814e7bb63b661804d0
Signed-off-by: Nicolas Le Bayon <nicolas.le.bayon@st.com>
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 684ab1a..c92bb54 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
@@ -9,10 +9,6 @@
#include <stdint.h>
#include <stdio.h>
-#include <libfdt.h>
-
-#include <platform_def.h>
-
#include <arch.h>
#include <arch_helpers.h>
#include <common/debug.h>
@@ -27,8 +23,11 @@
#include <lib/mmio.h>
#include <lib/spinlock.h>
#include <lib/utils_def.h>
+#include <libfdt.h>
#include <plat/common/platform.h>
+#include <platform_def.h>
+
#define MAX_HSI_HZ 64000000
#define USB_PHY_48_MHZ 48000000
@@ -1772,15 +1771,50 @@
mmio_clrsetbits_32(address, mask, value);
}
+static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg,
+ uint32_t *fracv, uint32_t *csg,
+ bool *csg_set)
+{
+ void *fdt;
+ int ret;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ ret = fdt_read_uint32_array(fdt, plloff, "cfg", (uint32_t)PLLCFG_NB,
+ pllcfg);
+ if (ret < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ *fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
+
+ ret = fdt_read_uint32_array(fdt, plloff, "csg", (uint32_t)PLLCSG_NB,
+ csg);
+
+ *csg_set = (ret == 0);
+
+ if (ret == -FDT_ERR_NOTFOUND) {
+ ret = 0;
+ }
+
+ return ret;
+}
+
int stm32mp1_clk_init(void)
{
uintptr_t rcc_base = stm32mp_rcc_base();
+ uint32_t pllfracv[_PLL_NB];
+ uint32_t pllcsg[_PLL_NB][PLLCSG_NB];
unsigned int clksrc[CLKSRC_NB];
unsigned int clkdiv[CLKDIV_NB];
unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
int plloff[_PLL_NB];
int ret, len;
enum stm32mp1_pll_id i;
+ bool pllcsg_set[_PLL_NB];
+ bool pllcfg_valid[_PLL_NB];
bool lse_css = false;
bool pll3_preserve = false;
bool pll4_preserve = false;
@@ -1817,14 +1851,16 @@
snprintf(name, sizeof(name), "st,pll@%d", i);
plloff[i] = fdt_rcc_subnode_offset(name);
- if (!fdt_check_node(plloff[i])) {
+ pllcfg_valid[i] = fdt_check_node(plloff[i]);
+ if (!pllcfg_valid[i]) {
continue;
}
- ret = fdt_read_uint32_array(fdt, plloff[i], "cfg",
- (int)PLLCFG_NB, pllcfg[i]);
- if (ret < 0) {
- return -FDT_ERR_NOTFOUND;
+ ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i],
+ &pllfracv[i], pllcsg[i],
+ &pllcsg_set[i]);
+ if (ret != 0) {
+ return ret;
}
}
@@ -1976,15 +2012,12 @@
/* Configure and start PLLs */
for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
- uint32_t fracv;
- uint32_t csg[PLLCSG_NB];
-
if (((i == _PLL3) && pll3_preserve) ||
((i == _PLL4) && pll4_preserve && !pll4_bootrom)) {
continue;
}
- if (!fdt_check_node(plloff[i])) {
+ if (!pllcfg_valid[i]) {
continue;
}
@@ -1994,25 +2027,20 @@
continue;
}
- fracv = fdt_read_uint32_default(fdt, plloff[i], "frac", 0);
-
- ret = stm32mp1_pll_config(i, pllcfg[i], fracv);
+ ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]);
if (ret != 0) {
return ret;
}
- ret = fdt_read_uint32_array(fdt, plloff[i], "csg",
- (uint32_t)PLLCSG_NB, csg);
- if (ret == 0) {
- stm32mp1_pll_csg(i, csg);
- } else if (ret != -FDT_ERR_NOTFOUND) {
- return ret;
+
+ if (pllcsg_set[i]) {
+ stm32mp1_pll_csg(i, pllcsg[i]);
}
stm32mp1_pll_start(i);
}
/* Wait and start PLLs ouptut when ready */
for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
- if (!fdt_check_node(plloff[i])) {
+ if (!pllcfg_valid[i]) {
continue;
}