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