From d412dd6d85bd10d5b2efb452121d1dc11db10225 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 6 Oct 2013 16:47:46 +0800 Subject: ARM: imx: replace imx6q_restart() with mxc_restart() The imx6q_restart() works fine with normal reboot but will run into problem with emergency reboot like sysrq-b. In that case, of_iomap() gets called from interrupt context and hence triggers the BUG_ON in __get_vm_area_node(). Actually, since commit c1e31d1 (ARM: imx: create mxc_arch_reset_init_dt() for DT boot), imx6q/dl should try to use mxc_restart() by calling mxc_arch_reset_init_dt() beforehand, where things like of_iomap() can be done. The patch updates mxc_restart() a little bit to get it work for imx6q/dl and kill imx6q_restart() completely. Reported-by: Nathan Lynch Signed-off-by: Shawn Guo (cherry picked from commit 87a84b69824d7fd63b20f3bc98d75c0238b8e7d0) Conflicts: arch/arm/mach-imx/mach-imx6q.c Signed-off-by: Robin Gong --- arch/arm/mach-imx/common.h | 4 +++ arch/arm/mach-imx/mach-imx6q.c | 58 ++---------------------------------------- arch/arm/mach-imx/system.c | 5 ++++ 3 files changed, 11 insertions(+), 56 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index ac2251da4316..ccab418fa3fc 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -132,7 +132,11 @@ static inline void imx_scu_standby_enable(void) {} extern void imx6_pm_map_io(void); extern void imx6_suspend(void); extern void imx_src_init(void); +#ifdef CONFIG_HAVE_IMX_SRC extern void imx_src_prepare_restart(void); +#else +static inline void imx_src_prepare_restart(void) {} +#endif extern void imx_gpc_init(void); extern void imx_gpc_pre_suspend(bool arm_power_off); extern void imx_gpc_post_resume(void); diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index aac2ab57fafa..f24c231ce38a 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -43,60 +42,6 @@ #include "cpuidle.h" #include "hardware.h" -static void imx6q_restart(char mode, const char *cmd) -{ - struct device_node *np; - void __iomem *wdog_base; - u32 wdog_source = 1; /* use WDOG1 default */ - unsigned int value; - - np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc"); - if (np) - of_property_read_u32(np, "fsl,wdog-reset", &wdog_source); - pr_info("Use WDOG%d as reset source\n", wdog_source); - - np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-wdt"); - wdog_base = of_iomap(np, 0); - if (!wdog_base) - goto soft; - - imx_src_prepare_restart(); - - if (wdog_source == 2) { - /* - * Some boards use WDOG2 to reset external pmic in bypass mode, - * so do WDOG2 reset here. Do not set SRS,since we will - * trigger external POR later. Use WDOG1 to reset in ldo-enable - * mode. - */ - np = of_find_compatible_node(np, NULL, "fsl,imx6q-wdt"); - wdog_base = of_iomap(np, 0); - if (!wdog_base) { - pr_warn("Not found wdt2, please check your dts!\n"); - goto soft; - } - value = 0x14; - } else { - value = (1 << 2); - } - /* enable wdog */ - writew_relaxed(value, wdog_base); - /* write twice to ensure the request will not get ignored */ - writew_relaxed(value, wdog_base); - - /* wait for reset to assert ... */ - mdelay(500); - - pr_err("Watchdog reset failed to assert reset\n"); - - /* delay to allow the serial port to show the message */ - mdelay(50); - -soft: - /* we'll take a jump through zero as a poor second */ - soft_restart(0); -} - static struct flexcan_platform_data flexcan_pdata[2]; static int flexcan_en_gpio; static int flexcan_stby_gpio; @@ -395,6 +340,7 @@ static void __init imx6q_init_machine(void) { struct device *parent; + mxc_arch_reset_init_dt(); parent = imx_soc_device_init(); if (parent == NULL) pr_warn("failed to initialize soc device\n"); @@ -566,5 +512,5 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)") .init_machine = imx6q_init_machine, .init_late = imx6q_init_late, .dt_compat = imx6q_dt_compat, - .restart = imx6q_restart, + .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index 5fc35ca82dad..ab4f7fa3d4da 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c @@ -42,6 +42,9 @@ void mxc_restart(char mode, const char *cmd) { unsigned int wcr_enable; + if (cpu_is_imx6q() || cpu_is_imx6dl()) + imx_src_prepare_restart(); + if (wdog_clk) clk_enable(wdog_clk); @@ -52,6 +55,8 @@ void mxc_restart(char mode, const char *cmd) /* Assert SRS signal */ __raw_writew(wcr_enable, wdog_base); + /* write twice to ensure the request will not get ignored */ + __raw_writew(wcr_enable, wdog_base); /* wait for reset to assert... */ mdelay(500); -- cgit v1.2.2