From 40b93075edba9077ed5fa49a57ddc366bc33f9aa Mon Sep 17 00:00:00 2001
From: Patrick Delaunay <patrick.delaunay@st.com>
Date: Fri, 4 Sep 2020 17:39:12 +0200
Subject: [PATCH] clk: stm32mp: preserved PLL4 for USB boot

The PLL4 can be use by ROM code as source clock of USB PHYC
In this case the PLL4 configuration must be preserved.

This patch add a error when the PLL4 configuration change
during the clock tree initialization.

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Change-Id: I4bae9312a2db8dd342a38e649513d689b13976bb
Reviewed-on: https://gerrit.st.com/c/mpu/oe/st/tf-a/+/177379
Reviewed-by: CITOOLS <smet-aci-reviews@lists.codex.cro.st.com>
Reviewed-by: Yann GAUTIER <yann.gautier@st.com>
Tested-by: Yann GAUTIER <yann.gautier@st.com>
---
 drivers/st/clk/stm32mp1_clk.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 564bd8798..577f965c6 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -1735,6 +1735,8 @@ int stm32mp1_clk_init(void)
 	bool pll4_bootrom = false;
 	const fdt32_t *pkcs_cell;
 	void *fdt;
+	int stgen_p = stm32mp1_clk_get_parent((int)STGEN_K);
+	int usbphy_p = stm32mp1_clk_get_parent((int)USBPHY_K);
 
 	if (fdt_get_address(&fdt) == 0) {
 		return false;
@@ -1834,6 +1836,12 @@ int stm32mp1_clk_init(void)
 							pllcfg[_PLL4],
 							plloff[_PLL4]);
 	}
+	/* Don't initialize PLL4, when used by BOOTROM */
+	if ((get_boot_device() == BOOT_DEVICE_USB) &&
+	    ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) {
+		pll4_bootrom = true;
+		pll4_preserve = true;
+	}
 
 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
 		if (((i == _PLL3) && pll3_preserve) ||
@@ -1985,6 +1993,11 @@ int stm32mp1_clk_init(void)
 	if (pkcs_cell != NULL) {
 		bool ckper_disabled = false;
 		uint32_t j;
+		uint32_t usbreg_bootrom = 0U;
+
+		if (pll4_bootrom) {
+			usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR);
+		}
 
 		for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
 			uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
@@ -2005,6 +2018,25 @@ int stm32mp1_clk_init(void)
 		if (ckper_disabled) {
 			stm32mp1_pkcs_config(CLK_CKPER_DISABLED);
 		}
+
+		if (pll4_bootrom) {
+			uint32_t usbreg_value, usbreg_mask;
+			const struct stm32mp1_clk_sel *sel;
+
+			sel = clk_sel_ref(_USBPHY_SEL);
+			usbreg_mask = (uint32_t)sel->msk << sel->src;
+			sel = clk_sel_ref(_USBO_SEL);
+			usbreg_mask |= (uint32_t)sel->msk << sel->src;
+
+			usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) &
+				       usbreg_mask;
+			usbreg_bootrom &= usbreg_mask;
+			if (usbreg_bootrom != usbreg_value) {
+				VERBOSE("forbidden new USB clk path\n");
+				VERBOSE("vs bootrom on USB boot\n");
+				return -FDT_ERR_BADVALUE;
+			}
+		}
 	}
 
 	/* Switch OFF HSI if not found in device-tree */
-- 
GitLab