2012-02-10 03:47:45 +04:00
/*
* arch / arm / mach - tegra / reset . c
*
* Copyright ( C ) 2011 , 2012 NVIDIA Corporation .
*
* This software is licensed under the terms of the GNU General Public
* License version 2 , as published by the Free Software Foundation , and
* may be copied , distributed , and modified under those terms .
*
* 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/init.h>
# include <linux/io.h>
# include <linux/cpumask.h>
# include <linux/bitops.h>
# include <asm/cacheflush.h>
# include <asm/hardware/cache-l2x0.h>
# include <mach/iomap.h>
# include <mach/irammap.h>
# include "reset.h"
# include "fuse.h"
# define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
TEGRA_IRAM_RESET_HANDLER_OFFSET )
static bool is_enabled ;
2012-06-19 01:01:50 +04:00
static void __init tegra_cpu_reset_handler_enable ( void )
2012-02-10 03:47:45 +04:00
{
void __iomem * iram_base = IO_ADDRESS ( TEGRA_IRAM_RESET_BASE ) ;
void __iomem * evp_cpu_reset =
IO_ADDRESS ( TEGRA_EXCEPTION_VECTORS_BASE + 0x100 ) ;
void __iomem * sb_ctrl = IO_ADDRESS ( TEGRA_SB_BASE ) ;
u32 reg ;
BUG_ON ( is_enabled ) ;
BUG_ON ( tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE ) ;
memcpy ( iram_base , ( void * ) __tegra_cpu_reset_handler_start ,
tegra_cpu_reset_handler_size ) ;
/*
* NOTE : This must be the one and only write to the EVP CPU reset
* vector in the entire system .
*/
writel ( TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset ,
evp_cpu_reset ) ;
wmb ( ) ;
reg = readl ( evp_cpu_reset ) ;
/*
* Prevent further modifications to the physical reset vector .
* NOTE : Has no effect on chips prior to Tegra30 .
*/
if ( tegra_chip_id ! = TEGRA20 ) {
reg = readl ( sb_ctrl ) ;
reg | = 2 ;
writel ( reg , sb_ctrl ) ;
wmb ( ) ;
}
is_enabled = true ;
}
void __init tegra_cpu_reset_handler_init ( void )
{
# ifdef CONFIG_SMP
__tegra_cpu_reset_handler_data [ TEGRA_RESET_MASK_PRESENT ] =
* ( ( u32 * ) cpu_present_mask ) ;
__tegra_cpu_reset_handler_data [ TEGRA_RESET_STARTUP_SECONDARY ] =
virt_to_phys ( ( void * ) tegra_secondary_startup ) ;
# endif
tegra_cpu_reset_handler_enable ( ) ;
}