@@ -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);
@@ -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)
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(+)