From da4a080a12375cecc2d9dff4680ec9d93c9a02ba Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Thu, 12 Sep 2013 16:34:01 +0800 Subject: ENGR00279402-2 ARM: imx6q: imx6sl: System reset by checking the source setting Check the source setting in dts file to support different WDOG reset event. Correct imx6sl_restart instead of mxc_restart. Signed-off-by: Robin Gong --- arch/arm/mach-imx/mach-imx6q.c | 28 +++++++++++++++++-- arch/arm/mach-imx/mach-imx6sl.c | 59 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index e92ee05b98a8..72b4d9fbc5d3 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -45,6 +45,13 @@ 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); @@ -53,10 +60,27 @@ static void imx6q_restart(char mode, const char *cmd) 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(1 << 2, wdog_base); + writew_relaxed(value, wdog_base); /* write twice to ensure the request will not get ignored */ - writew_relaxed(1 << 2, wdog_base); + writew_relaxed(value, wdog_base); /* wait for reset to assert ... */ mdelay(500); diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c index e1c83798bc3d..4265f1105b51 100644 --- a/arch/arm/mach-imx/mach-imx6sl.c +++ b/arch/arm/mach-imx/mach-imx6sl.c @@ -8,8 +8,10 @@ */ #include +#include #include #include +#include #include #include #include @@ -17,6 +19,7 @@ #include #include #include +#include #include "common.h" #include "cpuidle.h" @@ -26,6 +29,60 @@ static struct platform_device imx6sl_cpufreq_pdev = { .name = "imx6-cpufreq", }; +static void imx6sl_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,imx6sl-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,imx6sl-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. You can set it by "fsl,wodog-reset" in dts. + */ + np = of_find_compatible_node(np, NULL, "fsl,imx6sl-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 void __init imx6sl_fec_init(void) { struct regmap *gpr; @@ -137,5 +194,5 @@ DT_MACHINE_START(IMX6SL, "Freescale i.MX6 SoloLite (Device Tree)") .init_machine = imx6sl_init_machine, .init_late = imx6sl_init_late, .dt_compat = imx6sl_dt_compat, - .restart = mxc_restart, + .restart = imx6sl_restart, MACHINE_END -- cgit v1.2.2