From 7ae58c6ba79fee3cc032aae2105b073304409ebc Mon Sep 17 00:00:00 2001
From: Yann Gautier <yann.gautier@st.com>
Date: Thu, 14 Feb 2019 11:01:20 +0100
Subject: [PATCH] stm32mp1: use functions to retrieve some peripheral addresses

PWR, RCC, DDRPHYC & DDRCTRL addresses can be retrieved from device tree.
Platform asserts the value read from the DT are the SoC addresses.

Change-Id: I43f0890b51918a30c87ac067d3780ab27a0f59de
Signed-off-by: Yann Gautier <yann.gautier@st.com>
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
Signed-off-by: Nicolas LE BAYON <nicolas.le.bayon@st.com>
---
 drivers/st/ddr/stm32mp1_ddr_helpers.c   |  2 +-
 drivers/st/ddr/stm32mp1_ram.c           |  8 +--
 drivers/st/reset/stm32mp1_reset.c       | 10 ++--
 plat/st/common/include/stm32mp_common.h | 12 +++++
 plat/st/common/include/stm32mp_dt.h     |  3 ++
 plat/st/common/stm32mp_common.c         | 53 +++++++++++++++++++
 plat/st/common/stm32mp_dt.c             | 67 +++++++++++++++++++++++++
 plat/st/stm32mp1/bl2_plat_setup.c       | 19 ++++---
 plat/st/stm32mp1/stm32mp1_def.h         |  1 +
 plat/st/stm32mp1/stm32mp1_pm.c          |  3 +-
 10 files changed, 161 insertions(+), 17 deletions(-)

diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c
index e50b27be8..c66c9e707 100644
--- a/drivers/st/ddr/stm32mp1_ddr_helpers.c
+++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c
@@ -11,7 +11,7 @@
 
 void ddr_enable_clock(void)
 {
-	mmio_setbits_32(RCC_BASE + RCC_DDRITFCR,
+	mmio_setbits_32(stm32mp_rcc_base() + RCC_DDRITFCR,
 			RCC_DDRITFCR_DDRC1EN |
 			RCC_DDRITFCR_DDRC2EN |
 			RCC_DDRITFCR_DDRPHYCEN |
diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c
index 7b13385fc..59b4351f0 100644
--- a/drivers/st/ddr/stm32mp1_ram.c
+++ b/drivers/st/ddr/stm32mp1_ram.c
@@ -298,10 +298,10 @@ int stm32mp1_ddr_probe(void)
 
 	VERBOSE("STM32MP DDR probe\n");
 
-	priv->ctl = (struct stm32mp1_ddrctl *)DDRCTRL_BASE;
-	priv->phy = (struct stm32mp1_ddrphy *)DDRPHYC_BASE;
-	priv->pwr = PWR_BASE;
-	priv->rcc = RCC_BASE;
+	priv->ctl = (struct stm32mp1_ddrctl *)stm32mp_ddrctrl_base();
+	priv->phy = (struct stm32mp1_ddrphy *)stm32mp_ddrphyc_base();
+	priv->pwr = stm32mp_pwr_base();
+	priv->rcc = stm32mp_rcc_base();
 
 	priv->info.base = STM32MP_DDR_BASE;
 	priv->info.size = 0;
diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c
index b9a7ac7c9..b2de76085 100644
--- a/drivers/st/reset/stm32mp1_reset.c
+++ b/drivers/st/reset/stm32mp1_reset.c
@@ -20,9 +20,10 @@ void stm32mp_reset_assert(uint32_t id)
 {
 	uint32_t offset = (id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t);
 	uint32_t bit = id % (uint32_t)__LONG_BIT;
+	uintptr_t rcc_base = stm32mp_rcc_base();
 
-	mmio_write_32(RCC_BASE + offset, BIT(bit));
-	while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) == 0U) {
+	mmio_write_32(rcc_base + offset, BIT(bit));
+	while ((mmio_read_32(rcc_base + offset) & BIT(bit)) == 0U) {
 		;
 	}
 }
@@ -32,9 +33,10 @@ void stm32mp_reset_deassert(uint32_t id)
 	uint32_t offset = ((id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t)) +
 			  RST_CLR_OFFSET;
 	uint32_t bit = id % (uint32_t)__LONG_BIT;
+	uintptr_t rcc_base = stm32mp_rcc_base();
 
-	mmio_write_32(RCC_BASE + offset, BIT(bit));
-	while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) != 0U) {
+	mmio_write_32(rcc_base + offset, BIT(bit));
+	while ((mmio_read_32(rcc_base + offset) & BIT(bit)) != 0U) {
 		;
 	}
 }
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index 5f54b103d..fa0b63031 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -16,6 +16,18 @@
 void stm32mp_save_boot_ctx_address(uintptr_t address);
 uintptr_t stm32mp_get_boot_ctx_address(void);
 
+/* Return the base address of the DDR controller */
+uintptr_t stm32mp_ddrctrl_base(void);
+
+/* Return the base address of the DDR PHY */
+uintptr_t stm32mp_ddrphyc_base(void);
+
+/* Return the base address of the PWR peripheral */
+uintptr_t stm32mp_pwr_base(void);
+
+/* Return the base address of the RCC peripheral */
+uintptr_t stm32mp_rcc_base(void);
+
 /*
  * Platform util functions for the GPIO driver
  * @bank: Target GPIO bank ID as per DT bindings
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h
index 56357dbff..3415b051d 100644
--- a/plat/st/common/include/stm32mp_dt.h
+++ b/plat/st/common/include/stm32mp_dt.h
@@ -38,6 +38,9 @@ int dt_get_node(struct dt_node_info *info, int offset, const char *compat);
 int dt_get_stdout_uart_info(struct dt_node_info *info);
 int dt_get_stdout_node_offset(void);
 uint32_t dt_get_ddr_size(void);
+uintptr_t dt_get_ddrctrl_base(void);
+uintptr_t dt_get_ddrphyc_base(void);
+uintptr_t dt_get_pwr_base(void);
 const char *dt_get_board_model(void);
 
 #endif /* STM32MP_DT_H */
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
index aecef4718..2aba41e54 100644
--- a/plat/st/common/stm32mp_common.c
+++ b/plat/st/common/stm32mp_common.c
@@ -10,6 +10,7 @@
 
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/st/stm32mp_clkfunc.h>
 #include <plat/common/platform.h>
 
 uintptr_t plat_get_ns_image_entrypoint(void)
@@ -34,6 +35,58 @@ uintptr_t stm32mp_get_boot_ctx_address(void)
 	return boot_ctx_address;
 }
 
+uintptr_t stm32mp_ddrctrl_base(void)
+{
+	static uintptr_t ddrctrl_base;
+
+	if (ddrctrl_base == 0) {
+		ddrctrl_base = dt_get_ddrctrl_base();
+
+		assert(ddrctrl_base == DDRCTRL_BASE);
+	}
+
+	return ddrctrl_base;
+}
+
+uintptr_t stm32mp_ddrphyc_base(void)
+{
+	static uintptr_t ddrphyc_base;
+
+	if (ddrphyc_base == 0) {
+		ddrphyc_base = dt_get_ddrphyc_base();
+
+		assert(ddrphyc_base == DDRPHYC_BASE);
+	}
+
+	return ddrphyc_base;
+}
+
+uintptr_t stm32mp_pwr_base(void)
+{
+	static uintptr_t pwr_base;
+
+	if (pwr_base == 0) {
+		pwr_base = dt_get_pwr_base();
+
+		assert(pwr_base == PWR_BASE);
+	}
+
+	return pwr_base;
+}
+
+uintptr_t stm32mp_rcc_base(void)
+{
+	static uintptr_t rcc_base;
+
+	if (rcc_base == 0) {
+		rcc_base = fdt_rcc_read_addr();
+
+		assert(rcc_base == RCC_BASE);
+	}
+
+	return rcc_base;
+}
+
 uintptr_t stm32_get_gpio_bank_base(unsigned int bank)
 {
 	if (bank == GPIO_BANK_Z) {
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
index c0b0518d9..e64433bc8 100644
--- a/plat/st/common/stm32mp_dt.c
+++ b/plat/st/common/stm32mp_dt.c
@@ -291,6 +291,73 @@ uint32_t dt_get_ddr_size(void)
 	return fdt_read_uint32_default(node, "st,mem-size", 0);
 }
 
+/*******************************************************************************
+ * This function gets DDRCTRL base address information from the DT.
+ * Returns value on success, and 0 on failure.
+ ******************************************************************************/
+uintptr_t dt_get_ddrctrl_base(void)
+{
+	int node;
+	uint32_t array[4];
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
+	if (node < 0) {
+		INFO("%s: Cannot read DDR node in DT\n", __func__);
+		return 0;
+	}
+
+	if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
+		return 0;
+	}
+
+	return array[0];
+}
+
+/*******************************************************************************
+ * This function gets DDRPHYC base address information from the DT.
+ * Returns value on success, and 0 on failure.
+ ******************************************************************************/
+uintptr_t dt_get_ddrphyc_base(void)
+{
+	int node;
+	uint32_t array[4];
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
+	if (node < 0) {
+		INFO("%s: Cannot read DDR node in DT\n", __func__);
+		return 0;
+	}
+
+	if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
+		return 0;
+	}
+
+	return array[2];
+}
+
+/*******************************************************************************
+ * This function gets PWR base address information from the DT.
+ * Returns value on success, and 0 on failure.
+ ******************************************************************************/
+uintptr_t dt_get_pwr_base(void)
+{
+	int node;
+	const fdt32_t *cuint;
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
+	if (node < 0) {
+		INFO("%s: Cannot read PWR node in DT\n", __func__);
+		return 0;
+	}
+
+	cuint = fdt_getprop(fdt, node, "reg", NULL);
+	if (cuint == NULL) {
+		return 0;
+	}
+
+	return fdt32_to_cpu(*cuint);
+}
+
 /*******************************************************************************
  * This function retrieves board model from DT
  * Returns string taken from model node, NULL otherwise
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 69dc3fb10..5ab20845c 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -31,7 +31,7 @@ static struct console_stm32 console;
 
 static void print_reset_reason(void)
 {
-	uint32_t rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR);
+	uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR);
 
 	if (rstsr == 0U) {
 		WARN("Reset reason unknown\n");
@@ -147,6 +147,8 @@ void bl2_el3_plat_arch_setup(void)
 	boot_api_context_t *boot_context =
 		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
 	uint32_t clk_rate;
+	uintptr_t pwr_base;
+	uintptr_t rcc_base;
 
 	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
 			BL_CODE_END - BL_CODE_BASE,
@@ -174,27 +176,30 @@ void bl2_el3_plat_arch_setup(void)
 		panic();
 	}
 
+	pwr_base = stm32mp_pwr_base();
+	rcc_base = stm32mp_rcc_base();
+
 	/*
 	 * Disable the backup domain write protection.
 	 * The protection is enable at each reset by hardware
 	 * and must be disabled by software.
 	 */
-	mmio_setbits_32(PWR_BASE + PWR_CR1, PWR_CR1_DBP);
+	mmio_setbits_32(pwr_base + PWR_CR1, PWR_CR1_DBP);
 
-	while ((mmio_read_32(PWR_BASE + PWR_CR1) & PWR_CR1_DBP) == 0U) {
+	while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) {
 		;
 	}
 
 	/* Reset backup domain on cold boot cases */
-	if ((mmio_read_32(RCC_BASE + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) {
-		mmio_setbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST);
+	if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) {
+		mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
 
-		while ((mmio_read_32(RCC_BASE + RCC_BDCR) & RCC_BDCR_VSWRST) ==
+		while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) ==
 		       0U) {
 			;
 		}
 
-		mmio_clrbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST);
+		mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
 	}
 
 	generic_delay_timer_init();
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index beb588c7f..8d7cea327 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -253,6 +253,7 @@ static inline uint32_t tamp_bkpr(uint32_t idx)
 /*******************************************************************************
  * Device Tree defines
  ******************************************************************************/
+#define DT_PWR_COMPAT			"st,stm32mp1-pwr"
 #define DT_RCC_CLK_COMPAT		"st,stm32mp1-rcc"
 
 #endif /* STM32MP1_DEF_H */
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
index c4d023271..3262607a5 100644
--- a/plat/st/stm32mp1/stm32mp1_pm.c
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -159,7 +159,8 @@ static void __dead2 stm32_system_off(void)
 
 static void __dead2 stm32_system_reset(void)
 {
-	mmio_setbits_32(RCC_BASE + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPSYSRST);
+	mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
+			RCC_MP_GRSTCSETR_MPSYSRST);
 
 	/* Loop in case system reset is not immediately caught */
 	for ( ; ; ) {
-- 
GitLab