diff options
author | Robin Gong <b38343@freescale.com> | 2013-09-12 16:34:01 +0800 |
---|---|---|
committer | Robin Gong <b38343@freescale.com> | 2013-09-12 18:23:38 +0800 |
commit | 227a2ac95ca08359a4d8c1ce39d5d0d2bd898c46 (patch) | |
tree | 9a9fa27d0a5280dc72c9d4780e2cf9ccd57dc0dc | |
parent | aaba72937410b795cb952eafc4549903cbb45ca5 (diff) |
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 <b38343@freescale.com>
-rw-r--r-- | arch/arm/mach-imx/mach-imx6q.c | 28 | ||||
-rw-r--r-- | 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 <linux/clk-provider.h> +#include <linux/delay.h> #include <linux/irqchip.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/opp.h> #include <linux/regmap.h> @@ -17,6 +19,7 @@ #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> +#include <asm/system_misc.h> #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 |