aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2013-10-06 04:47:46 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:47:12 -0400
commitd412dd6d85bd10d5b2efb452121d1dc11db10225 (patch)
tree50474ac43fc9d85a253e6bfd4205ee35c866f534
parent2fad0e34c5adbddf3d73e25fc42222a0ceabd5dd (diff)
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 <nathan_lynch@mentor.com> Signed-off-by: Shawn Guo <shawn.guo@linaro.org> (cherry picked from commit 87a84b69824d7fd63b20f3bc98d75c0238b8e7d0) Conflicts: arch/arm/mach-imx/mach-imx6q.c Signed-off-by: Robin Gong <b38343@freescale.com>
-rw-r--r--arch/arm/mach-imx/common.h4
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c58
-rw-r--r--arch/arm/mach-imx/system.c5
3 files changed, 11 insertions, 56 deletions
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) {}
132extern void imx6_pm_map_io(void); 132extern void imx6_pm_map_io(void);
133extern void imx6_suspend(void); 133extern void imx6_suspend(void);
134extern void imx_src_init(void); 134extern void imx_src_init(void);
135#ifdef CONFIG_HAVE_IMX_SRC
135extern void imx_src_prepare_restart(void); 136extern void imx_src_prepare_restart(void);
137#else
138static inline void imx_src_prepare_restart(void) {}
139#endif
136extern void imx_gpc_init(void); 140extern void imx_gpc_init(void);
137extern void imx_gpc_pre_suspend(bool arm_power_off); 141extern void imx_gpc_pre_suspend(bool arm_power_off);
138extern void imx_gpc_post_resume(void); 142extern 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 @@
16#include <linux/clkdev.h> 16#include <linux/clkdev.h>
17#include <linux/clocksource.h> 17#include <linux/clocksource.h>
18#include <linux/cpu.h> 18#include <linux/cpu.h>
19#include <linux/delay.h>
20#include <linux/export.h> 19#include <linux/export.h>
21#include <linux/gpio.h> 20#include <linux/gpio.h>
22#include <linux/init.h> 21#include <linux/init.h>
@@ -43,60 +42,6 @@
43#include "cpuidle.h" 42#include "cpuidle.h"
44#include "hardware.h" 43#include "hardware.h"
45 44
46static void imx6q_restart(char mode, const char *cmd)
47{
48 struct device_node *np;
49 void __iomem *wdog_base;
50 u32 wdog_source = 1; /* use WDOG1 default */
51 unsigned int value;
52
53 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
54 if (np)
55 of_property_read_u32(np, "fsl,wdog-reset", &wdog_source);
56 pr_info("Use WDOG%d as reset source\n", wdog_source);
57
58 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-wdt");
59 wdog_base = of_iomap(np, 0);
60 if (!wdog_base)
61 goto soft;
62
63 imx_src_prepare_restart();
64
65 if (wdog_source == 2) {
66 /*
67 * Some boards use WDOG2 to reset external pmic in bypass mode,
68 * so do WDOG2 reset here. Do not set SRS,since we will
69 * trigger external POR later. Use WDOG1 to reset in ldo-enable
70 * mode.
71 */
72 np = of_find_compatible_node(np, NULL, "fsl,imx6q-wdt");
73 wdog_base = of_iomap(np, 0);
74 if (!wdog_base) {
75 pr_warn("Not found wdt2, please check your dts!\n");
76 goto soft;
77 }
78 value = 0x14;
79 } else {
80 value = (1 << 2);
81 }
82 /* enable wdog */
83 writew_relaxed(value, wdog_base);
84 /* write twice to ensure the request will not get ignored */
85 writew_relaxed(value, wdog_base);
86
87 /* wait for reset to assert ... */
88 mdelay(500);
89
90 pr_err("Watchdog reset failed to assert reset\n");
91
92 /* delay to allow the serial port to show the message */
93 mdelay(50);
94
95soft:
96 /* we'll take a jump through zero as a poor second */
97 soft_restart(0);
98}
99
100static struct flexcan_platform_data flexcan_pdata[2]; 45static struct flexcan_platform_data flexcan_pdata[2];
101static int flexcan_en_gpio; 46static int flexcan_en_gpio;
102static int flexcan_stby_gpio; 47static int flexcan_stby_gpio;
@@ -395,6 +340,7 @@ static void __init imx6q_init_machine(void)
395{ 340{
396 struct device *parent; 341 struct device *parent;
397 342
343 mxc_arch_reset_init_dt();
398 parent = imx_soc_device_init(); 344 parent = imx_soc_device_init();
399 if (parent == NULL) 345 if (parent == NULL)
400 pr_warn("failed to initialize soc device\n"); 346 pr_warn("failed to initialize soc device\n");
@@ -566,5 +512,5 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
566 .init_machine = imx6q_init_machine, 512 .init_machine = imx6q_init_machine,
567 .init_late = imx6q_init_late, 513 .init_late = imx6q_init_late,
568 .dt_compat = imx6q_dt_compat, 514 .dt_compat = imx6q_dt_compat,
569 .restart = imx6q_restart, 515 .restart = mxc_restart,
570MACHINE_END 516MACHINE_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)
42{ 42{
43 unsigned int wcr_enable; 43 unsigned int wcr_enable;
44 44
45 if (cpu_is_imx6q() || cpu_is_imx6dl())
46 imx_src_prepare_restart();
47
45 if (wdog_clk) 48 if (wdog_clk)
46 clk_enable(wdog_clk); 49 clk_enable(wdog_clk);
47 50
@@ -52,6 +55,8 @@ void mxc_restart(char mode, const char *cmd)
52 55
53 /* Assert SRS signal */ 56 /* Assert SRS signal */
54 __raw_writew(wcr_enable, wdog_base); 57 __raw_writew(wcr_enable, wdog_base);
58 /* write twice to ensure the request will not get ignored */
59 __raw_writew(wcr_enable, wdog_base);
55 60
56 /* wait for reset to assert... */ 61 /* wait for reset to assert... */
57 mdelay(500); 62 mdelay(500);