ARM: 7198/1: arm/imx6: add restart support for imx6q
The restart support was missed from the initial imx6q submission. The mxc_restart() does not work for imx6q. Instead, this patch adds the restart for imx6q. Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
@@ -1931,14 +1931,12 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
|
|||||||
val |= 0x1 << BP_CLPCR_LPM;
|
val |= 0x1 << BP_CLPCR_LPM;
|
||||||
val &= ~BM_CLPCR_VSTBY;
|
val &= ~BM_CLPCR_VSTBY;
|
||||||
val &= ~BM_CLPCR_SBYOS;
|
val &= ~BM_CLPCR_SBYOS;
|
||||||
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
|
|
||||||
break;
|
break;
|
||||||
case STOP_POWER_OFF:
|
case STOP_POWER_OFF:
|
||||||
val |= 0x2 << BP_CLPCR_LPM;
|
val |= 0x2 << BP_CLPCR_LPM;
|
||||||
val |= 0x3 << BP_CLPCR_STBY_COUNT;
|
val |= 0x3 << BP_CLPCR_STBY_COUNT;
|
||||||
val |= BM_CLPCR_VSTBY;
|
val |= BM_CLPCR_VSTBY;
|
||||||
val |= BM_CLPCR_SBYOS;
|
val |= BM_CLPCR_SBYOS;
|
||||||
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@@ -10,10 +10,13 @@
|
|||||||
* http://www.gnu.org/copyleft/gpl.html
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <asm/hardware/cache-l2x0.h>
|
#include <asm/hardware/cache-l2x0.h>
|
||||||
@@ -23,6 +26,36 @@
|
|||||||
#include <mach/common.h>
|
#include <mach/common.h>
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
|
|
||||||
|
void imx6q_restart(char mode, const char *cmd)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
void __iomem *wdog_base;
|
||||||
|
|
||||||
|
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-wdt");
|
||||||
|
wdog_base = of_iomap(np, 0);
|
||||||
|
if (!wdog_base)
|
||||||
|
goto soft;
|
||||||
|
|
||||||
|
imx_src_prepare_restart();
|
||||||
|
|
||||||
|
/* enable wdog */
|
||||||
|
writew_relaxed(1 << 2, wdog_base);
|
||||||
|
/* write twice to ensure the request will not get ignored */
|
||||||
|
writew_relaxed(1 << 2, 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 imx6q_init_machine(void)
|
static void __init imx6q_init_machine(void)
|
||||||
{
|
{
|
||||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||||
@@ -83,5 +116,5 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
|
|||||||
.timer = &imx6q_timer,
|
.timer = &imx6q_timer,
|
||||||
.init_machine = imx6q_init_machine,
|
.init_machine = imx6q_init_machine,
|
||||||
.dt_compat = imx6q_dt_compat,
|
.dt_compat = imx6q_dt_compat,
|
||||||
.restart = mxc_restart,
|
.restart = imx6q_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#define SRC_SCR 0x000
|
#define SRC_SCR 0x000
|
||||||
#define SRC_GPR1 0x020
|
#define SRC_GPR1 0x020
|
||||||
|
#define BP_SRC_SCR_WARM_RESET_ENABLE 0
|
||||||
#define BP_SRC_SCR_CORE1_RST 14
|
#define BP_SRC_SCR_CORE1_RST 14
|
||||||
#define BP_SRC_SCR_CORE1_ENABLE 22
|
#define BP_SRC_SCR_CORE1_ENABLE 22
|
||||||
|
|
||||||
@@ -46,11 +47,33 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)
|
|||||||
src_base + SRC_GPR1 + cpu * 8);
|
src_base + SRC_GPR1 + cpu * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void imx_src_prepare_restart(void)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
/* clear enable bits of secondary cores */
|
||||||
|
val = readl_relaxed(src_base + SRC_SCR);
|
||||||
|
val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE);
|
||||||
|
writel_relaxed(val, src_base + SRC_SCR);
|
||||||
|
|
||||||
|
/* clear persistent entry register of primary core */
|
||||||
|
writel_relaxed(0, src_base + SRC_GPR1);
|
||||||
|
}
|
||||||
|
|
||||||
void __init imx_src_init(void)
|
void __init imx_src_init(void)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
|
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
|
||||||
src_base = of_iomap(np, 0);
|
src_base = of_iomap(np, 0);
|
||||||
WARN_ON(!src_base);
|
WARN_ON(!src_base);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* force warm reset sources to generate cold reset
|
||||||
|
* for a more reliable restart
|
||||||
|
*/
|
||||||
|
val = readl_relaxed(src_base + SRC_SCR);
|
||||||
|
val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
|
||||||
|
writel_relaxed(val, src_base + SRC_SCR);
|
||||||
}
|
}
|
||||||
|
@@ -122,6 +122,7 @@ static inline void imx_smp_prepare(void) {}
|
|||||||
extern void imx_enable_cpu(int cpu, bool enable);
|
extern void imx_enable_cpu(int cpu, bool enable);
|
||||||
extern void imx_set_cpu_jump(int cpu, void *jump_addr);
|
extern void imx_set_cpu_jump(int cpu, void *jump_addr);
|
||||||
extern void imx_src_init(void);
|
extern void imx_src_init(void);
|
||||||
|
extern void imx_src_prepare_restart(void);
|
||||||
extern void imx_gpc_init(void);
|
extern void imx_gpc_init(void);
|
||||||
extern void imx_gpc_pre_suspend(void);
|
extern void imx_gpc_pre_suspend(void);
|
||||||
extern void imx_gpc_post_resume(void);
|
extern void imx_gpc_post_resume(void);
|
||||||
|
Reference in New Issue
Block a user