summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gong <b38343@freescale.com>2013-09-12 16:34:01 +0800
committerRobin Gong <b38343@freescale.com>2013-09-12 18:23:38 +0800
commit227a2ac95ca08359a4d8c1ce39d5d0d2bd898c46 (patch)
tree9a9fa27d0a5280dc72c9d4780e2cf9ccd57dc0dc
parentaaba72937410b795cb952eafc4549903cbb45ca5 (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.c28
-rw-r--r--arch/arm/mach-imx/mach-imx6sl.c59
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