@@ -12,6 +12,7 @@
&rst {
u-boot,dm-pre-reloc;
+ altr,modrst-reset-val = <1 0xffffffbf 0xffffffff>;
};
&sdr {
@@ -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
@@ -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();
@@ -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,
};
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@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(-)