2008-07-05 10:02:56 +02:00
/*
* Copyright ( C ) 1999 ARM Limited
* Copyright ( C ) 2000 Deep Blue Solutions Ltd
* Copyright 2006 - 2007 Freescale Semiconductor , Inc . All Rights Reserved .
* Copyright 2008 Juergen Beisert , kernel @ pengutronix . de
2009-03-03 02:49:23 +03:00
* Copyright 2009 Ilya Yanok , Emcraft Systems Ltd , yanok @ emcraft . com
2008-07-05 10:02:56 +02:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
# include <linux/kernel.h>
# include <linux/clk.h>
# include <linux/io.h>
2009-03-03 02:49:23 +03:00
# include <linux/err.h>
# include <linux/delay.h>
2013-05-10 10:19:01 +08:00
# include <linux/of.h>
# include <linux/of_address.h>
2008-07-05 10:02:56 +02:00
2012-03-28 18:30:01 +01:00
# include <asm/system_misc.h>
2008-07-05 10:02:56 +02:00
# include <asm/proc-fns.h>
2010-10-27 14:40:55 +02:00
# include <asm/mach-types.h>
2013-07-08 21:45:20 +08:00
# include <asm/hardware/cache-l2x0.h>
2008-07-05 10:02:56 +02:00
2012-09-13 21:01:00 +08:00
# include "common.h"
2012-09-14 14:14:45 +08:00
# include "hardware.h"
2012-09-13 21:01:00 +08:00
2009-06-04 12:19:02 +02:00
static void __iomem * wdog_base ;
2013-05-10 09:13:44 +08:00
static struct clk * wdog_clk ;
2008-07-05 10:02:56 +02:00
/*
* Reset the system . It is called by machine_restart ( ) .
*/
2013-07-08 16:01:40 -07:00
void mxc_restart ( enum reboot_mode mode , const char * cmd )
2008-07-05 10:02:56 +02:00
{
2009-06-04 12:19:02 +02:00
unsigned int wcr_enable ;
2013-05-10 09:13:44 +08:00
if ( wdog_clk )
clk_enable ( wdog_clk ) ;
2008-07-05 10:02:56 +02:00
2013-05-10 09:13:44 +08:00
if ( cpu_is_mx1 ( ) )
wcr_enable = ( 1 < < 0 ) ;
else
2009-06-04 12:19:02 +02:00
wcr_enable = ( 1 < < 2 ) ;
2008-07-05 10:02:56 +02:00
/* Assert SRS signal */
2009-06-04 12:19:02 +02:00
__raw_writew ( wcr_enable , wdog_base ) ;
2013-10-31 10:35:40 +08:00
/*
* Due to imx6q errata ERR004346 ( WDOG : WDOG SRS bit requires to be
* written twice ) , we add another two writes to ensure there must be at
* least two writes happen in the same one 32 kHz clock period . We save
* the target check here , since the writes shouldn ' t be a huge burden
* for other platforms .
*/
__raw_writew ( wcr_enable , wdog_base ) ;
2013-10-06 16:47:46 +08:00
__raw_writew ( wcr_enable , wdog_base ) ;
2009-03-03 02:49:23 +03:00
/* wait for reset to assert... */
mdelay ( 500 ) ;
2013-05-10 09:13:44 +08:00
pr_err ( " %s: Watchdog reset failed to assert reset \n " , __func__ ) ;
2009-03-03 02:49:23 +03:00
/* delay to allow the serial port to show the message */
mdelay ( 50 ) ;
/* we'll take a jump through zero as a poor second */
2011-11-01 13:16:26 +00:00
soft_restart ( 0 ) ;
2008-07-05 10:02:56 +02:00
}
2009-06-04 12:19:02 +02:00
2013-05-10 09:13:44 +08:00
void __init mxc_arch_reset_init ( void __iomem * base )
2009-06-04 12:19:02 +02:00
{
wdog_base = base ;
2013-05-10 09:13:44 +08:00
wdog_clk = clk_get_sys ( " imx2-wdt.0 " , NULL ) ;
if ( IS_ERR ( wdog_clk ) ) {
pr_warn ( " %s: failed to get wdog clock \n " , __func__ ) ;
wdog_clk = NULL ;
return ;
}
clk_prepare ( wdog_clk ) ;
2009-06-04 12:19:02 +02:00
}
2013-05-10 10:19:01 +08:00
void __init mxc_arch_reset_init_dt ( void )
{
struct device_node * np ;
np = of_find_compatible_node ( NULL , NULL , " fsl,imx21-wdt " ) ;
wdog_base = of_iomap ( np , 0 ) ;
WARN_ON ( ! wdog_base ) ;
wdog_clk = of_clk_get ( np , 0 ) ;
if ( IS_ERR ( wdog_clk ) ) {
pr_warn ( " %s: failed to get wdog clock \n " , __func__ ) ;
wdog_clk = NULL ;
return ;
}
clk_prepare ( wdog_clk ) ;
}
2013-07-08 21:45:20 +08:00
# ifdef CONFIG_CACHE_L2X0
2013-07-10 11:45:46 +02:00
void __init imx_init_l2cache ( void )
2013-07-08 21:45:20 +08:00
{
void __iomem * l2x0_base ;
struct device_node * np ;
unsigned int val ;
np = of_find_compatible_node ( NULL , NULL , " arm,pl310-cache " ) ;
if ( ! np )
goto out ;
l2x0_base = of_iomap ( np , 0 ) ;
if ( ! l2x0_base ) {
of_node_put ( np ) ;
goto out ;
}
/* Configure the L2 PREFETCH and POWER registers */
val = readl_relaxed ( l2x0_base + L2X0_PREFETCH_CTRL ) ;
val | = 0x70800000 ;
2013-09-16 09:29:03 +08:00
/*
* The L2 cache controller ( PL310 ) version on the i . MX6D / Q is r3p1 - 50 rel0
* The L2 cache controller ( PL310 ) version on the i . MX6DL / SOLO / SL is r3p2
* But according to ARM PL310 errata : 752271
* ID : 752271 : Double linefill feature can cause data corruption
* Fault Status : Present in : r3p0 , r3p1 , r3p1 - 50 rel0 . Fixed in r3p2
* Workaround : The only workaround to this erratum is to disable the
* double linefill feature . This is the default behavior .
*/
if ( cpu_is_imx6q ( ) )
val & = ~ ( 1 < < 30 | 1 < < 23 ) ;
2013-07-08 21:45:20 +08:00
writel_relaxed ( val , l2x0_base + L2X0_PREFETCH_CTRL ) ;
val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN ;
writel_relaxed ( val , l2x0_base + L2X0_POWER_CTRL ) ;
iounmap ( l2x0_base ) ;
of_node_put ( np ) ;
out :
l2x0_of_init ( 0 , ~ 0UL ) ;
}
# endif