diff mbox series

rk3328: request that SoC resets use the first reset

Message ID 66qwutykozwkh6veu6ojbmwp4glmefrvkncyu6gytdpy76kj2k@fpgggo4wczpt (mailing list archive)
State New
Headers show
Series rk3328: request that SoC resets use the first reset | expand

Commit Message

Simonas Kazlauskas Dec. 25, 2024, 10:23 p.m. UTC
On my test board (Radxa RockPiE)/setup the second reset does not appear
to be working at all - requesting second reset even as early as inside
the U-Boot will entirely hang the CPU with the only way to recover from
it being to pull physical RST pin to ground or to power cycle the
device. While there may be ways to set up the second reset such that it
would work correctly, it is pretty clear to me that at least Linux
doesn't do that currently.

SOC reset sources (watchdog timer in particular) defaults to using the
second type of reset, so any attempts to use the feature on my board are
unsuccessful. Instead of the SoC reset, a hang occurs.

This change makes a request that SoC reset sources use the first reset;
the same one as the regular reset that occurs as part of a regular
reboot.

Context: The second type of reset is supposed to preserve GPIO and GRF
state, which to me sounds undesirable, especially for WDT use: what if
the GPIO/GRF state was exactly the part that led to WDT elapse?

Note: I do not have any other Rockchip hardware currently to test if the
behaviour extends to other SoCs by this manufacturer. As thus the
implementation is self-contained to rk3328 currently.

Signed-off-by: Simonas Kazlauskas <linux@kazlauskas.me>
---
  drivers/clk/rockchip/clk-rk3328.c | 15 +++++++++++++++
  drivers/clk/rockchip/clk.h        |  1 +
  2 files changed, 16 insertions(+)
diff mbox series

Patch

diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c
index 3bb87b27b662..9ef2d53341e0 100644
--- a/drivers/clk/rockchip/clk-rk3328.c
+++ b/drivers/clk/rockchip/clk-rk3328.c
@@ -878,6 +878,20 @@  static const char *const rk3328_critical_clocks[] __initconst = {
  	"pclk_phy_niu",
  };
  
+#define RK3328_TSADC_GLB_SRST_CTRL_MASK		(1 << 14)
+#define RK3328_WDT_GLB_SRST_CTRL_MASK		(1 << 14)
+
+static void rk3328_soc_rst_init(void __iomem *reg_base)
+{
+	void __iomem *glb_cnt_address;
+	uint32_t previous_value;
+
+	glb_cnt_address = reg_base + RK3328_GLB_CNT_TH;
+	previous_value = readl(glb_cnt_address);
+	writel(previous | RK3328_TSADC_GLB_SRST_CTRL_MASK | RK3328_WDT_GLB_SRST_CTRL_MASK,
+	       glb_cnt_address);
+}
+
  static void __init rk3328_clk_init(struct device_node *np)
  {
  	struct rockchip_clk_provider *ctx;
@@ -890,6 +904,7 @@  static void __init rk3328_clk_init(struct device_node *np)
  		return;
  	}
  
+	rk3328_soc_rst_init(reg_base);
  	clk_nr_clks = rockchip_clk_find_max_clk_id(rk3328_clk_branches,
  						   ARRAY_SIZE(rk3328_clk_branches)) + 1;
  	ctx = rockchip_clk_init(np, reg_base, clk_nr_clks);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index f1957e1c1178..bf5f23952064 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -157,6 +157,7 @@  struct clk;
  #define RK3328_CLKSEL_CON(x)		((x) * 0x4 + 0x100)
  #define RK3328_CLKGATE_CON(x)		((x) * 0x4 + 0x200)
  #define RK3328_GRFCLKSEL_CON(x)		((x) * 0x4 + 0x100)
+#define RK3328_GLB_CNT_TH		0x90
  #define RK3328_GLB_SRST_FST		0x9c
  #define RK3328_GLB_SRST_SND		0x98
  #define RK3328_SOFTRST_CON(x)		((x) * 0x4 + 0x300)