xref: /openbmc/linux/arch/arm/mach-imx/system.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
23995eb82SShawn Guo /*
33995eb82SShawn Guo  * Copyright (C) 1999 ARM Limited
43995eb82SShawn Guo  * Copyright (C) 2000 Deep Blue Solutions Ltd
53995eb82SShawn Guo  * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
63995eb82SShawn Guo  * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
73995eb82SShawn Guo  * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com
83995eb82SShawn Guo  */
93995eb82SShawn Guo 
103995eb82SShawn Guo #include <linux/kernel.h>
113995eb82SShawn Guo #include <linux/clk.h>
123995eb82SShawn Guo #include <linux/io.h>
133995eb82SShawn Guo #include <linux/err.h>
143995eb82SShawn Guo #include <linux/delay.h>
15c1e31d12SShawn Guo #include <linux/of.h>
16c1e31d12SShawn Guo #include <linux/of_address.h>
173995eb82SShawn Guo 
183995eb82SShawn Guo #include <asm/system_misc.h>
193995eb82SShawn Guo #include <asm/proc-fns.h>
203995eb82SShawn Guo #include <asm/mach-types.h>
21e6a07569SShawn Guo #include <asm/hardware/cache-l2x0.h>
223995eb82SShawn Guo 
23e3372474SShawn Guo #include "common.h"
2450f2de61SShawn Guo #include "hardware.h"
25e3372474SShawn Guo 
263995eb82SShawn Guo static void __iomem *wdog_base;
2718cb680fSShawn Guo static struct clk *wdog_clk;
286f98cb22SArnd Bergmann static int wcr_enable = (1 << 2);
293995eb82SShawn Guo 
303995eb82SShawn Guo /*
313995eb82SShawn Guo  * Reset the system. It is called by machine_restart().
323995eb82SShawn Guo  */
mxc_restart(enum reboot_mode mode,const char * cmd)337b6d864bSRobin Holt void mxc_restart(enum reboot_mode mode, const char *cmd)
343995eb82SShawn Guo {
355a6e1502SAlexander Shiyan 	if (!wdog_base)
365a6e1502SAlexander Shiyan 		goto reset_fallback;
375a6e1502SAlexander Shiyan 
38ce8ad883SAlexander Shiyan 	if (!IS_ERR(wdog_clk))
3918cb680fSShawn Guo 		clk_enable(wdog_clk);
403995eb82SShawn Guo 
413995eb82SShawn Guo 	/* Assert SRS signal */
42c553138fSJohannes Berg 	imx_writew(wcr_enable, wdog_base);
432c11b57aSShawn Guo 	/*
442c11b57aSShawn Guo 	 * Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be
452c11b57aSShawn Guo 	 * written twice), we add another two writes to ensure there must be at
462c11b57aSShawn Guo 	 * least two writes happen in the same one 32kHz clock period.  We save
472c11b57aSShawn Guo 	 * the target check here, since the writes shouldn't be a huge burden
482c11b57aSShawn Guo 	 * for other platforms.
492c11b57aSShawn Guo 	 */
50c553138fSJohannes Berg 	imx_writew(wcr_enable, wdog_base);
51c553138fSJohannes Berg 	imx_writew(wcr_enable, wdog_base);
523995eb82SShawn Guo 
533995eb82SShawn Guo 	/* wait for reset to assert... */
543995eb82SShawn Guo 	mdelay(500);
553995eb82SShawn Guo 
5618cb680fSShawn Guo 	pr_err("%s: Watchdog reset failed to assert reset\n", __func__);
573995eb82SShawn Guo 
583995eb82SShawn Guo 	/* delay to allow the serial port to show the message */
593995eb82SShawn Guo 	mdelay(50);
603995eb82SShawn Guo 
615a6e1502SAlexander Shiyan reset_fallback:
623995eb82SShawn Guo 	/* we'll take a jump through zero as a poor second */
633995eb82SShawn Guo 	soft_restart(0);
643995eb82SShawn Guo }
653995eb82SShawn Guo 
mxc_arch_reset_init(void __iomem * base)6618cb680fSShawn Guo void __init mxc_arch_reset_init(void __iomem *base)
673995eb82SShawn Guo {
683995eb82SShawn Guo 	wdog_base = base;
6918cb680fSShawn Guo 
7018cb680fSShawn Guo 	wdog_clk = clk_get_sys("imx2-wdt.0", NULL);
71ce8ad883SAlexander Shiyan 	if (IS_ERR(wdog_clk))
7218cb680fSShawn Guo 		pr_warn("%s: failed to get wdog clock\n", __func__);
73ce8ad883SAlexander Shiyan 	else
7418cb680fSShawn Guo 		clk_prepare(wdog_clk);
753995eb82SShawn Guo }
76c1e31d12SShawn Guo 
776f98cb22SArnd Bergmann #ifdef CONFIG_SOC_IMX1
imx1_reset_init(void __iomem * base)786f98cb22SArnd Bergmann void __init imx1_reset_init(void __iomem *base)
796f98cb22SArnd Bergmann {
806f98cb22SArnd Bergmann 	wcr_enable = (1 << 0);
816f98cb22SArnd Bergmann 	mxc_arch_reset_init(base);
826f98cb22SArnd Bergmann }
836f98cb22SArnd Bergmann #endif
846f98cb22SArnd Bergmann 
85e6a07569SShawn Guo #ifdef CONFIG_CACHE_L2X0
imx_init_l2cache(void)8610eff770SVincent Stehlé void __init imx_init_l2cache(void)
87e6a07569SShawn Guo {
88e6a07569SShawn Guo 	void __iomem *l2x0_base;
89e6a07569SShawn Guo 	struct device_node *np;
90e6a07569SShawn Guo 	unsigned int val;
91e6a07569SShawn Guo 
92e6a07569SShawn Guo 	np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
93e6a07569SShawn Guo 	if (!np)
94510aca64SAndrey Smirnov 		return;
95e6a07569SShawn Guo 
96e6a07569SShawn Guo 	l2x0_base = of_iomap(np, 0);
97510aca64SAndrey Smirnov 	if (!l2x0_base)
98510aca64SAndrey Smirnov 		goto put_node;
99e6a07569SShawn Guo 
100c00e4c54SAndrey Smirnov 	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
101e6a07569SShawn Guo 		/* Configure the L2 PREFETCH and POWER registers */
1021a5a954cSRussell King 		val = readl_relaxed(l2x0_base + L310_PREFETCH_CTRL);
103b8290371SAndrey Smirnov 		val |= L310_PREFETCH_CTRL_DBL_LINEFILL |
104b8290371SAndrey Smirnov 			L310_PREFETCH_CTRL_INSTR_PREFETCH |
1051d9e9477SAndrey Smirnov 			L310_PREFETCH_CTRL_DATA_PREFETCH;
1061d9e9477SAndrey Smirnov 
1071d9e9477SAndrey Smirnov 		/* Set perfetch offset to improve performance */
1081d9e9477SAndrey Smirnov 		val &= ~L310_PREFETCH_CTRL_OFFSET_MASK;
1091d9e9477SAndrey Smirnov 		val |= 15;
1101d9e9477SAndrey Smirnov 
1111a5a954cSRussell King 		writel_relaxed(val, l2x0_base + L310_PREFETCH_CTRL);
112c00e4c54SAndrey Smirnov 	}
113e6a07569SShawn Guo 
114e6a07569SShawn Guo 	iounmap(l2x0_base);
115510aca64SAndrey Smirnov put_node:
116e6a07569SShawn Guo 	of_node_put(np);
117e6a07569SShawn Guo }
118e6a07569SShawn Guo #endif
119