2010-12-18 21:39:27 +08:00
/*
* Copyright ( C ) 1999 ARM Limited
* Copyright ( C ) 2000 Deep Blue Solutions Ltd
* Copyright 2006 - 2007 , 2010 Freescale Semiconductor , Inc . All Rights Reserved .
* Copyright 2008 Juergen Beisert , kernel @ pengutronix . de
* Copyright 2009 Ilya Yanok , Emcraft Systems Ltd , yanok @ emcraft . com
*
* 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>
# include <linux/err.h>
# include <linux/delay.h>
# include <linux/init.h>
2011-02-16 10:46:12 +01:00
# include <linux/module.h>
2010-12-18 21:39:27 +08:00
# include <asm/proc-fns.h>
2012-03-28 18:30:01 +01:00
# include <asm/system_misc.h>
2010-12-18 21:39:27 +08:00
# include <mach/mxs.h>
# include <mach/common.h>
# define MX23_CLKCTRL_RESET_OFFSET 0x120
# define MX28_CLKCTRL_RESET_OFFSET 0x1e0
# define MXS_CLKCTRL_RESET_CHIP (1 << 1)
# define MXS_MODULE_CLKGATE (1 << 30)
# define MXS_MODULE_SFTRST (1 << 31)
static void __iomem * mxs_clkctrl_reset_addr ;
/*
* Reset the system . It is called by machine_restart ( ) .
*/
2011-11-05 15:43:30 +00:00
void mxs_restart ( char mode , const char * cmd )
2010-12-18 21:39:27 +08:00
{
/* reset the chip */
__mxs_setl ( MXS_CLKCTRL_RESET_CHIP , mxs_clkctrl_reset_addr ) ;
pr_err ( " Failed to assert the chip reset \n " ) ;
/* 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 ) ;
2010-12-18 21:39:27 +08:00
}
static int __init mxs_arch_reset_init ( void )
{
struct clk * clk ;
mxs_clkctrl_reset_addr = MXS_IO_ADDRESS ( MXS_CLKCTRL_BASE_ADDR ) +
( cpu_is_mx23 ( ) ? MX23_CLKCTRL_RESET_OFFSET :
MX28_CLKCTRL_RESET_OFFSET ) ;
clk = clk_get_sys ( " rtc " , NULL ) ;
if ( ! IS_ERR ( clk ) )
2011-12-20 13:50:11 +08:00
clk_prepare_enable ( clk ) ;
2010-12-18 21:39:27 +08:00
return 0 ;
}
core_initcall ( mxs_arch_reset_init ) ;
/*
* Clear the bit and poll it cleared . This is usually called with
* a reset address and mask being either SFTRST ( bit 31 ) or CLKGATE
* ( bit 30 ) .
*/
static int clear_poll_bit ( void __iomem * addr , u32 mask )
{
int timeout = 0x400 ;
/* clear the bit */
__mxs_clrl ( mask , addr ) ;
/*
* SFTRST needs 3 GPMI clocks to settle , the reference manual
* recommends to wait 1u s .
*/
udelay ( 1 ) ;
/* poll the bit becoming clear */
while ( ( __raw_readl ( addr ) & mask ) & & - - timeout )
/* nothing */ ;
return ! timeout ;
}
int mxs_reset_block ( void __iomem * reset_addr )
{
int ret ;
int timeout = 0x400 ;
/* clear and poll SFTRST */
ret = clear_poll_bit ( reset_addr , MXS_MODULE_SFTRST ) ;
if ( unlikely ( ret ) )
goto error ;
/* clear CLKGATE */
__mxs_clrl ( MXS_MODULE_CLKGATE , reset_addr ) ;
/* set SFTRST to reset the block */
__mxs_setl ( MXS_MODULE_SFTRST , reset_addr ) ;
udelay ( 1 ) ;
/* poll CLKGATE becoming set */
while ( ( ! ( __raw_readl ( reset_addr ) & MXS_MODULE_CLKGATE ) ) & & - - timeout )
/* nothing */ ;
if ( unlikely ( ! timeout ) )
goto error ;
/* clear and poll SFTRST */
ret = clear_poll_bit ( reset_addr , MXS_MODULE_SFTRST ) ;
if ( unlikely ( ret ) )
goto error ;
/* clear and poll CLKGATE */
ret = clear_poll_bit ( reset_addr , MXS_MODULE_CLKGATE ) ;
if ( unlikely ( ret ) )
goto error ;
return 0 ;
error :
pr_err ( " %s(%p): module reset timeout \n " , __func__ , reset_addr ) ;
return - ETIMEDOUT ;
}
2011-02-16 10:46:12 +01:00
EXPORT_SYMBOL ( mxs_reset_block ) ;