Commit 1d33929e authored by Chris Zhong's avatar Chris Zhong Committed by Heiko Stuebner

clk: rockchip: switch PLLs to slow mode before reboot for rk3288

We've been seeing some crashes at reboot test on rk3288-based systems,
which boards have not reset pin connected to NPOR, they reboot by
setting 0xfdb9 to RK3288_GLB_SRST_FST register. If the APLL works in
a high frequency mode, some IPs might hang during soft reset.
It appears that we can fix the problem by switching to slow mode before
reboot, just like what we did before suspend.
Signed-off-by: default avatarChris Zhong <zyw@rock-chips.com>
Signed-off-by: default avatarHeiko Stuebner <heiko@sntech.de>
parent a2f4c560
...@@ -783,10 +783,10 @@ static const char *const rk3288_critical_clocks[] __initconst = { ...@@ -783,10 +783,10 @@ static const char *const rk3288_critical_clocks[] __initconst = {
"pclk_pd_pmu", "pclk_pd_pmu",
}; };
#ifdef CONFIG_PM_SLEEP
static void __iomem *rk3288_cru_base; static void __iomem *rk3288_cru_base;
/* Some CRU registers will be reset in maskrom when the system /*
* Some CRU registers will be reset in maskrom when the system
* wakes up from fastboot. * wakes up from fastboot.
* So save them before suspend, restore them after resume. * So save them before suspend, restore them after resume.
*/ */
...@@ -840,33 +840,28 @@ static void rk3288_clk_resume(void) ...@@ -840,33 +840,28 @@ static void rk3288_clk_resume(void)
} }
} }
static void rk3288_clk_shutdown(void)
{
writel_relaxed(0xf3030000, rk3288_cru_base + RK3288_MODE_CON);
}
static struct syscore_ops rk3288_clk_syscore_ops = { static struct syscore_ops rk3288_clk_syscore_ops = {
.suspend = rk3288_clk_suspend, .suspend = rk3288_clk_suspend,
.resume = rk3288_clk_resume, .resume = rk3288_clk_resume,
.shutdown = rk3288_clk_shutdown,
}; };
static void rk3288_clk_sleep_init(void __iomem *reg_base)
{
rk3288_cru_base = reg_base;
register_syscore_ops(&rk3288_clk_syscore_ops);
}
#else /* CONFIG_PM_SLEEP */
static void rk3288_clk_sleep_init(void __iomem *reg_base) {}
#endif
static void __init rk3288_clk_init(struct device_node *np) static void __init rk3288_clk_init(struct device_node *np)
{ {
void __iomem *reg_base;
struct clk *clk; struct clk *clk;
reg_base = of_iomap(np, 0); rk3288_cru_base = of_iomap(np, 0);
if (!reg_base) { if (!rk3288_cru_base) {
pr_err("%s: could not map cru region\n", __func__); pr_err("%s: could not map cru region\n", __func__);
return; return;
} }
rockchip_clk_init(np, reg_base, CLK_NR_CLKS); rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS);
/* xin12m is created by an cru-internal divider */ /* xin12m is created by an cru-internal divider */
clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
...@@ -907,10 +902,11 @@ static void __init rk3288_clk_init(struct device_node *np) ...@@ -907,10 +902,11 @@ static void __init rk3288_clk_init(struct device_node *np)
&rk3288_cpuclk_data, rk3288_cpuclk_rates, &rk3288_cpuclk_data, rk3288_cpuclk_rates,
ARRAY_SIZE(rk3288_cpuclk_rates)); ARRAY_SIZE(rk3288_cpuclk_rates));
rockchip_register_softrst(np, 12, reg_base + RK3288_SOFTRST_CON(0), rockchip_register_softrst(np, 12,
rk3288_cru_base + RK3288_SOFTRST_CON(0),
ROCKCHIP_SOFTRST_HIWORD_MASK); ROCKCHIP_SOFTRST_HIWORD_MASK);
rockchip_register_restart_notifier(RK3288_GLB_SRST_FST); rockchip_register_restart_notifier(RK3288_GLB_SRST_FST);
rk3288_clk_sleep_init(reg_base); register_syscore_ops(&rk3288_clk_syscore_ops);
} }
CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment