diff options
author | Shawn Guo <shawn.guo@linaro.org> | 2013-10-06 04:47:46 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:47:12 -0400 |
commit | d412dd6d85bd10d5b2efb452121d1dc11db10225 (patch) | |
tree | 50474ac43fc9d85a253e6bfd4205ee35c866f534 | |
parent | 2fad0e34c5adbddf3d73e25fc42222a0ceabd5dd (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.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6q.c | 58 | ||||
-rw-r--r-- | arch/arm/mach-imx/system.c | 5 |
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) {} | |||
132 | extern void imx6_pm_map_io(void); | 132 | extern void imx6_pm_map_io(void); |
133 | extern void imx6_suspend(void); | 133 | extern void imx6_suspend(void); |
134 | extern void imx_src_init(void); | 134 | extern void imx_src_init(void); |
135 | #ifdef CONFIG_HAVE_IMX_SRC | ||
135 | extern void imx_src_prepare_restart(void); | 136 | extern void imx_src_prepare_restart(void); |
137 | #else | ||
138 | static inline void imx_src_prepare_restart(void) {} | ||
139 | #endif | ||
136 | extern void imx_gpc_init(void); | 140 | extern void imx_gpc_init(void); |
137 | extern void imx_gpc_pre_suspend(bool arm_power_off); | 141 | extern void imx_gpc_pre_suspend(bool arm_power_off); |
138 | extern void imx_gpc_post_resume(void); | 142 | 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 @@ | |||
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 | ||
46 | static 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 | |||
95 | soft: | ||
96 | /* we'll take a jump through zero as a poor second */ | ||
97 | soft_restart(0); | ||
98 | } | ||
99 | |||
100 | static struct flexcan_platform_data flexcan_pdata[2]; | 45 | static struct flexcan_platform_data flexcan_pdata[2]; |
101 | static int flexcan_en_gpio; | 46 | static int flexcan_en_gpio; |
102 | static int flexcan_stby_gpio; | 47 | static 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, |
570 | MACHINE_END | 516 | 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) | |||
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); |