18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 1999 ARM Limited 48c2ecf20Sopenharmony_ci * Copyright (C) 2000 Deep Blue Solutions Ltd 58c2ecf20Sopenharmony_ci * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved. 68c2ecf20Sopenharmony_ci * Copyright 2008 Juergen Beisert, kernel@pengutronix.de 78c2ecf20Sopenharmony_ci * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/clk.h> 128c2ecf20Sopenharmony_ci#include <linux/io.h> 138c2ecf20Sopenharmony_ci#include <linux/err.h> 148c2ecf20Sopenharmony_ci#include <linux/delay.h> 158c2ecf20Sopenharmony_ci#include <linux/of.h> 168c2ecf20Sopenharmony_ci#include <linux/of_address.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <asm/system_misc.h> 198c2ecf20Sopenharmony_ci#include <asm/proc-fns.h> 208c2ecf20Sopenharmony_ci#include <asm/mach-types.h> 218c2ecf20Sopenharmony_ci#include <asm/hardware/cache-l2x0.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include "common.h" 248c2ecf20Sopenharmony_ci#include "hardware.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic void __iomem *wdog_base; 278c2ecf20Sopenharmony_cistatic struct clk *wdog_clk; 288c2ecf20Sopenharmony_cistatic int wcr_enable = (1 << 2); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* 318c2ecf20Sopenharmony_ci * Reset the system. It is called by machine_restart(). 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_civoid mxc_restart(enum reboot_mode mode, const char *cmd) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci if (!wdog_base) 368c2ecf20Sopenharmony_ci goto reset_fallback; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci if (!IS_ERR(wdog_clk)) 398c2ecf20Sopenharmony_ci clk_enable(wdog_clk); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci /* Assert SRS signal */ 428c2ecf20Sopenharmony_ci imx_writew(wcr_enable, wdog_base); 438c2ecf20Sopenharmony_ci /* 448c2ecf20Sopenharmony_ci * Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be 458c2ecf20Sopenharmony_ci * written twice), we add another two writes to ensure there must be at 468c2ecf20Sopenharmony_ci * least two writes happen in the same one 32kHz clock period. We save 478c2ecf20Sopenharmony_ci * the target check here, since the writes shouldn't be a huge burden 488c2ecf20Sopenharmony_ci * for other platforms. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_ci imx_writew(wcr_enable, wdog_base); 518c2ecf20Sopenharmony_ci imx_writew(wcr_enable, wdog_base); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* wait for reset to assert... */ 548c2ecf20Sopenharmony_ci mdelay(500); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci pr_err("%s: Watchdog reset failed to assert reset\n", __func__); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* delay to allow the serial port to show the message */ 598c2ecf20Sopenharmony_ci mdelay(50); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cireset_fallback: 628c2ecf20Sopenharmony_ci /* we'll take a jump through zero as a poor second */ 638c2ecf20Sopenharmony_ci soft_restart(0); 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_civoid __init mxc_arch_reset_init(void __iomem *base) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci wdog_base = base; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci wdog_clk = clk_get_sys("imx2-wdt.0", NULL); 718c2ecf20Sopenharmony_ci if (IS_ERR(wdog_clk)) 728c2ecf20Sopenharmony_ci pr_warn("%s: failed to get wdog clock\n", __func__); 738c2ecf20Sopenharmony_ci else 748c2ecf20Sopenharmony_ci clk_prepare(wdog_clk); 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#ifdef CONFIG_SOC_IMX1 788c2ecf20Sopenharmony_civoid __init imx1_reset_init(void __iomem *base) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci wcr_enable = (1 << 0); 818c2ecf20Sopenharmony_ci mxc_arch_reset_init(base); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci#endif 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#ifdef CONFIG_CACHE_L2X0 868c2ecf20Sopenharmony_civoid __init imx_init_l2cache(void) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci void __iomem *l2x0_base; 898c2ecf20Sopenharmony_ci struct device_node *np; 908c2ecf20Sopenharmony_ci unsigned int val; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache"); 938c2ecf20Sopenharmony_ci if (!np) 948c2ecf20Sopenharmony_ci return; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci l2x0_base = of_iomap(np, 0); 978c2ecf20Sopenharmony_ci if (!l2x0_base) 988c2ecf20Sopenharmony_ci goto put_node; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { 1018c2ecf20Sopenharmony_ci /* Configure the L2 PREFETCH and POWER registers */ 1028c2ecf20Sopenharmony_ci val = readl_relaxed(l2x0_base + L310_PREFETCH_CTRL); 1038c2ecf20Sopenharmony_ci val |= L310_PREFETCH_CTRL_DBL_LINEFILL | 1048c2ecf20Sopenharmony_ci L310_PREFETCH_CTRL_INSTR_PREFETCH | 1058c2ecf20Sopenharmony_ci L310_PREFETCH_CTRL_DATA_PREFETCH; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* Set perfetch offset to improve performance */ 1088c2ecf20Sopenharmony_ci val &= ~L310_PREFETCH_CTRL_OFFSET_MASK; 1098c2ecf20Sopenharmony_ci val |= 15; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci writel_relaxed(val, l2x0_base + L310_PREFETCH_CTRL); 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci iounmap(l2x0_base); 1158c2ecf20Sopenharmony_ciput_node: 1168c2ecf20Sopenharmony_ci of_node_put(np); 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci#endif 119