[U-Boot] [RFC PATCH v2 05/18] arm: socfpga: gen5: move initial reset handling to reset driver

Simon Goldschmidt simon.k.r.goldschmidt at gmail.com
Tue Oct 15 20:10:18 UTC 2019


This moves disabling all peripherals from ad-hoc code in arch/arm
to the socfpga reset driver.

To do this, DM initialization and UCLASS_RESET probing has to be done
earlier in the SPL. Also, the gen5 devicetrees need an added property
that tells the reset driver which bits to set and which need to be
left at 0 (L4WD0).

Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt at gmail.com>
---

Changes in v2:
- add dts based reset handling (messed up in v1)

 arch/arm/dts/socfpga-common-u-boot.dtsi    |  1 +
 arch/arm/mach-socfpga/reset_manager_gen5.c | 13 --------
 arch/arm/mach-socfpga/spl_gen5.c           | 21 ++++++------
 drivers/reset/reset-socfpga.c              | 37 ++++++++++++++++++++--
 4 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/arch/arm/dts/socfpga-common-u-boot.dtsi b/arch/arm/dts/socfpga-common-u-boot.dtsi
index 322c858c4b..aebe476e3f 100644
--- a/arch/arm/dts/socfpga-common-u-boot.dtsi
+++ b/arch/arm/dts/socfpga-common-u-boot.dtsi
@@ -12,6 +12,7 @@
 
 &rst {
 	u-boot,dm-pre-reloc;
+	altr,modrst-reset-val = <1 0xffffffbf 0xffffffff>;
 };
 
 &sdr {
diff --git a/arch/arm/mach-socfpga/reset_manager_gen5.c b/arch/arm/mach-socfpga/reset_manager_gen5.c
index 9a32f5abfe..34e59b852b 100644
--- a/arch/arm/mach-socfpga/reset_manager_gen5.c
+++ b/arch/arm/mach-socfpga/reset_manager_gen5.c
@@ -48,19 +48,6 @@ void socfpga_per_reset(u32 reset, int set)
 		clrbits_le32(reg, 1 << RSTMGR_RESET(reset));
 }
 
-/*
- * Assert reset on every peripheral but L4WD0.
- * Watchdog must be kept intact to prevent glitches
- * and/or hangs.
- */
-void socfpga_per_reset_all(void)
-{
-	const u32 l4wd0 = 1 << RSTMGR_RESET(SOCFPGA_RESET(L4WD0));
-
-	writel(~l4wd0, &reset_manager_base->per_mod_reset);
-	writel(0xffffffff, &reset_manager_base->per2_mod_reset);
-}
-
 #define L3REGS_REMAP_LWHPS2FPGA_MASK	0x10
 #define L3REGS_REMAP_HPS2FPGA_MASK	0x08
 #define L3REGS_REMAP_OCRAM_MASK		0x01
diff --git a/arch/arm/mach-socfpga/spl_gen5.c b/arch/arm/mach-socfpga/spl_gen5.c
index 87b76b47de..1ae8025746 100644
--- a/arch/arm/mach-socfpga/spl_gen5.c
+++ b/arch/arm/mach-socfpga/spl_gen5.c
@@ -84,12 +84,19 @@ void board_init_f(ulong dummy)
 	socfpga_sdram_remap_zero();
 	socfpga_pl310_clear();
 
+	ret = spl_early_init();
+	if (ret) {
+		debug("spl_early_init() failed: %d\n", ret);
+		hang();
+	}
+
 	debug("Freezing all I/O banks\n");
 	/* freeze all IO banks */
 	sys_mgr_frzctrl_freeze_req();
 
-	/* Put everything into reset but L4WD0. */
-	socfpga_per_reset_all();
+	ret = uclass_get_device(UCLASS_RESET, 0, &dev);
+	if (ret)
+		debug("Reset init failed: %d\n", ret);
 
 	if (!socfpga_is_booting_from_fpga()) {
 		/* Put FPGA bridges into reset too. */
@@ -130,16 +137,6 @@ void board_init_f(ulong dummy)
 	debug_uart_init();
 #endif
 
-	ret = spl_early_init();
-	if (ret) {
-		debug("spl_early_init() failed: %d\n", ret);
-		hang();
-	}
-
-	ret = uclass_get_device(UCLASS_RESET, 0, &dev);
-	if (ret)
-		debug("Reset init failed: %d\n", ret);
-
 	/* enable console uart printing */
 	preloader_console_init();
 
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
index 93ec9cfdb6..c5fd0679c7 100644
--- a/drivers/reset/reset-socfpga.c
+++ b/drivers/reset/reset-socfpga.c
@@ -106,6 +106,39 @@ static const struct reset_ops socfpga_reset_ops = {
 	.rst_deassert = socfpga_reset_deassert,
 };
 
+/*
+ * This function ensures that in SPL, all peripherals are reset at startup.
+ * It does this by reading reset values from the device tree.
+ */
+static int socfpga_reset_set_inital_reset_values(struct udevice *dev)
+{
+#ifdef CONFIG_SPL_BUILD
+	struct socfpga_reset_data *data = dev_get_priv(dev);
+	int ret;
+	u32 modrst_vals[5];
+	size_t i, sz, offset;
+
+	ret = dev_read_size(dev, "altr,modrst-reset-val");
+	if (ret >= sizeof(u32)) {
+		sz = min(ret/sizeof(u32), ARRAY_SIZE(modrst_vals));
+		ret = dev_read_u32_array(dev, "altr,modrst-reset-val",
+					 modrst_vals, sz);
+		if (ret) {
+			dev_warn(dev, "Failed to read modrst reset values\n");
+			return ret;
+		}
+		/* first item is register offset to start */
+		offset = modrst_vals[0] * 4;
+		for (i = 1; i < sz; i++) {
+			writel(modrst_vals[i], data->modrst_base + offset);
+			offset += 4;
+		}
+	}
+#endif
+
+	return 0;
+}
+
 static int socfpga_reset_probe(struct udevice *dev)
 {
 	struct socfpga_reset_data *data = dev_get_priv(dev);
@@ -117,7 +150,7 @@ static int socfpga_reset_probe(struct udevice *dev)
 	modrst_offset = dev_read_u32_default(dev, "altr,modrst-offset", 0x10);
 	data->modrst_base = membase + modrst_offset;
 
-	return 0;
+	return socfpga_reset_set_inital_reset_values(dev);
 }
 
 static int socfpga_reset_remove(struct udevice *dev)
@@ -163,5 +196,5 @@ U_BOOT_DRIVER(socfpga_reset) = {
 	.priv_auto_alloc_size = sizeof(struct socfpga_reset_data),
 	.ops = &socfpga_reset_ops,
 	.remove = socfpga_reset_remove,
-	.flags	= DM_FLAG_OS_PREPARE,
+	.flags	= DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE,
 };
-- 
2.20.1



More information about the U-Boot mailing list