drivers: stm32mp1 clocks: allow tree lookup for several system clocks

Oscillators, PLLs and some system clocks can be related straight to
a parent clock. Prior this change were only oscillators and few
clocks supported by this look up. This changes adds PLLs and other
system clocks. This enables for flexible use of clock tree exploration
when computing a clock frequency value.

Change-Id: I15ec98023a7095e3120a6954de59a4799d92c66b
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 540c66a..2036945 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -106,10 +106,61 @@
 	_MCUS_SEL,
 	_USBPHY_SEL,
 	_USBO_SEL,
+	_MPU_SEL,
+	_PER_SEL,
 	_PARENT_SEL_NB,
 	_UNKNOWN_SEL = 0xff,
 };
 
+/* State the parent clock ID straight related to a clock */
+static const uint8_t parent_id_clock_id[_PARENT_NB] = {
+	[_HSE] = CK_HSE,
+	[_HSI] = CK_HSI,
+	[_CSI] = CK_CSI,
+	[_LSE] = CK_LSE,
+	[_LSI] = CK_LSI,
+	[_I2S_CKIN] = _UNKNOWN_ID,
+	[_USB_PHY_48] = _UNKNOWN_ID,
+	[_HSI_KER] = CK_HSI,
+	[_HSE_KER] = CK_HSE,
+	[_HSE_KER_DIV2] = CK_HSE_DIV2,
+	[_CSI_KER] = CK_CSI,
+	[_PLL1_P] = PLL1_P,
+	[_PLL1_Q] = PLL1_Q,
+	[_PLL1_R] = PLL1_R,
+	[_PLL2_P] = PLL2_P,
+	[_PLL2_Q] = PLL2_Q,
+	[_PLL2_R] = PLL2_R,
+	[_PLL3_P] = PLL3_P,
+	[_PLL3_Q] = PLL3_Q,
+	[_PLL3_R] = PLL3_R,
+	[_PLL4_P] = PLL4_P,
+	[_PLL4_Q] = PLL4_Q,
+	[_PLL4_R] = PLL4_R,
+	[_ACLK] = CK_AXI,
+	[_PCLK1] = CK_AXI,
+	[_PCLK2] = CK_AXI,
+	[_PCLK3] = CK_AXI,
+	[_PCLK4] = CK_AXI,
+	[_PCLK5] = CK_AXI,
+	[_CK_PER] = CK_PER,
+	[_CK_MPU] = CK_MPU,
+	[_CK_MCU] = CK_MCU,
+};
+
+static unsigned int clock_id2parent_id(unsigned long id)
+{
+	unsigned int n;
+
+	for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) {
+		if (parent_id_clock_id[n] == id) {
+			return n;
+		}
+	}
+
+	return _UNKNOWN_ID;
+}
+
 enum stm32mp1_pll_id {
 	_PLL1,
 	_PLL2,
@@ -281,19 +332,6 @@
 		.refclk[3] = (p4),			\
 	}
 
-static const uint8_t stm32mp1_clks[][2] = {
-	{ CK_PER, _CK_PER },
-	{ CK_MPU, _CK_MPU },
-	{ CK_AXI, _ACLK },
-	{ CK_MCU, _CK_MCU },
-	{ CK_HSE, _HSE },
-	{ CK_CSI, _CSI },
-	{ CK_LSI, _LSI },
-	{ CK_LSE, _LSE },
-	{ CK_HSI, _HSI },
-	{ CK_HSE_DIV2, _HSE_KER_DIV2 },
-};
-
 #define NB_GATES	ARRAY_SIZE(stm32mp1_clk_gate)
 
 static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
@@ -440,6 +478,14 @@
 	_PLL4_R, _USB_PHY_48
 };
 
+static const uint8_t mpu_parents[] = {
+	_HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */
+};
+
+static const uint8_t per_parents[] = {
+	_HSI, _HSE, _CSI,
+};
+
 static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
 	_CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents),
 	_CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents),
@@ -448,6 +494,8 @@
 	_CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents),
 	_CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
 	_CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
+	_CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents),
+	_CLK_PARENT_SEL(PER, RCC_CPERCKSELR, per_parents),
 	_CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
 	_CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
 	_CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents),
@@ -618,16 +666,16 @@
 static int stm32mp1_clk_get_parent(unsigned long id)
 {
 	const struct stm32mp1_clk_sel *sel;
-	uint32_t j, p_sel;
+	uint32_t p_sel;
 	int i;
 	enum stm32mp1_parent_id p;
 	enum stm32mp1_parent_sel s;
 	uintptr_t rcc_base = stm32mp_rcc_base();
 
-	for (j = 0U; j < ARRAY_SIZE(stm32mp1_clks); j++) {
-		if (stm32mp1_clks[j][0] == id) {
-			return (int)stm32mp1_clks[j][1];
-		}
+	/* Few non gateable clock have a static parent ID, find them */
+	i = (int)clock_id2parent_id(id);
+	if (i != _UNKNOWN_ID) {
+		return i;
 	}
 
 	i = stm32mp1_clk_get_gated_id(id);
diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h
index 4b4aac8..2ffc3b2 100644
--- a/include/drivers/st/stm32mp1_rcc.h
+++ b/include/drivers/st/stm32mp1_rcc.h
@@ -250,6 +250,8 @@
 #define RCC_MPCKSELR_HSE		0x00000001
 #define RCC_MPCKSELR_PLL		0x00000002
 #define RCC_MPCKSELR_PLL_MPUDIV		0x00000003
+#define RCC_MPCKSELR_MPUSRC_MASK	GENMASK(1, 0)
+#define RCC_MPCKSELR_MPUSRC_SHIFT	0
 
 /* Values of RCC_ASSCKSELR register */
 #define RCC_ASSCKSELR_HSI		0x00000000
@@ -266,6 +268,8 @@
 #define RCC_CPERCKSELR_HSI		0x00000000
 #define RCC_CPERCKSELR_CSI		0x00000001
 #define RCC_CPERCKSELR_HSE		0x00000002
+#define RCC_CPERCKSELR_PERSRC_MASK	GENMASK(1, 0)
+#define RCC_CPERCKSELR_PERSRC_SHIFT	0
 
 /* Used for most of DIVR register: max div for RTC */
 #define RCC_DIVR_DIV_MASK		GENMASK(5, 0)