2011-09-06 14:39:44 +08:00
/*
* Copyright 2011 Freescale Semiconductor , Inc .
* Copyright 2011 Linaro Ltd .
*
* The code contained herein is licensed under the GNU General Public
* License . You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations :
*
* http : //www.opensource.org/licenses/gpl-license.html
* http : //www.gnu.org/copyleft/gpl.html
*/
# include <linux/init.h>
# include <linux/io.h>
# include <linux/of.h>
# include <linux/of_address.h>
2013-03-28 17:35:19 +01:00
# include <linux/reset-controller.h>
2011-08-09 12:24:07 +01:00
# include <linux/smp.h>
2012-01-20 12:01:12 +01:00
# include <asm/smp_plat.h>
2013-03-25 09:20:43 -03:00
# include "common.h"
2011-09-06 14:39:44 +08:00
# define SRC_SCR 0x000
# define SRC_GPR1 0x020
2011-12-09 00:51:26 +01:00
# define BP_SRC_SCR_WARM_RESET_ENABLE 0
2013-03-28 17:35:19 +01:00
# define BP_SRC_SCR_SW_GPU_RST 1
# define BP_SRC_SCR_SW_VPU_RST 2
# define BP_SRC_SCR_SW_IPU1_RST 3
# define BP_SRC_SCR_SW_OPEN_VG_RST 4
# define BP_SRC_SCR_SW_IPU2_RST 12
2011-09-06 14:39:44 +08:00
# define BP_SRC_SCR_CORE1_RST 14
# define BP_SRC_SCR_CORE1_ENABLE 22
static void __iomem * src_base ;
2013-03-28 17:35:19 +01:00
static DEFINE_SPINLOCK ( scr_lock ) ;
static const int sw_reset_bits [ 5 ] = {
BP_SRC_SCR_SW_GPU_RST ,
BP_SRC_SCR_SW_VPU_RST ,
BP_SRC_SCR_SW_IPU1_RST ,
BP_SRC_SCR_SW_OPEN_VG_RST ,
BP_SRC_SCR_SW_IPU2_RST
} ;
static int imx_src_reset_module ( struct reset_controller_dev * rcdev ,
unsigned long sw_reset_idx )
{
unsigned long timeout ;
unsigned long flags ;
int bit ;
u32 val ;
if ( ! src_base )
return - ENODEV ;
if ( sw_reset_idx > = ARRAY_SIZE ( sw_reset_bits ) )
return - EINVAL ;
bit = 1 < < sw_reset_bits [ sw_reset_idx ] ;
spin_lock_irqsave ( & scr_lock , flags ) ;
val = readl_relaxed ( src_base + SRC_SCR ) ;
val | = bit ;
writel_relaxed ( val , src_base + SRC_SCR ) ;
spin_unlock_irqrestore ( & scr_lock , flags ) ;
timeout = jiffies + msecs_to_jiffies ( 1000 ) ;
while ( readl ( src_base + SRC_SCR ) & bit ) {
if ( time_after ( jiffies , timeout ) )
return - ETIME ;
cpu_relax ( ) ;
}
return 0 ;
}
static struct reset_control_ops imx_src_ops = {
. reset = imx_src_reset_module ,
} ;
static struct reset_controller_dev imx_reset_controller = {
. ops = & imx_src_ops ,
. nr_resets = ARRAY_SIZE ( sw_reset_bits ) ,
} ;
2011-09-06 14:39:44 +08:00
void imx_enable_cpu ( int cpu , bool enable )
{
u32 mask , val ;
2011-08-09 12:24:07 +01:00
cpu = cpu_logical_map ( cpu ) ;
2011-09-06 14:39:44 +08:00
mask = 1 < < ( BP_SRC_SCR_CORE1_ENABLE + cpu - 1 ) ;
2013-03-28 17:35:19 +01:00
spin_lock ( & scr_lock ) ;
2011-09-06 14:39:44 +08:00
val = readl_relaxed ( src_base + SRC_SCR ) ;
val = enable ? val | mask : val & ~ mask ;
2013-10-09 15:54:31 +08:00
val | = 1 < < ( BP_SRC_SCR_CORE1_RST + cpu - 1 ) ;
2011-09-06 14:39:44 +08:00
writel_relaxed ( val , src_base + SRC_SCR ) ;
2013-03-28 17:35:19 +01:00
spin_unlock ( & scr_lock ) ;
2011-09-06 14:39:44 +08:00
}
void imx_set_cpu_jump ( int cpu , void * jump_addr )
{
2011-08-09 12:24:07 +01:00
cpu = cpu_logical_map ( cpu ) ;
2012-01-09 15:41:40 -06:00
writel_relaxed ( virt_to_phys ( jump_addr ) ,
2011-09-06 14:39:44 +08:00
src_base + SRC_GPR1 + cpu * 8 ) ;
}
2013-03-26 16:46:07 +08:00
u32 imx_get_cpu_arg ( int cpu )
{
cpu = cpu_logical_map ( cpu ) ;
return readl_relaxed ( src_base + SRC_GPR1 + cpu * 8 + 4 ) ;
}
void imx_set_cpu_arg ( int cpu , u32 arg )
{
cpu = cpu_logical_map ( cpu ) ;
writel_relaxed ( arg , src_base + SRC_GPR1 + cpu * 8 + 4 ) ;
}
2011-09-06 14:39:44 +08:00
void __init imx_src_init ( void )
{
struct device_node * np ;
2011-12-09 00:51:26 +01:00
u32 val ;
2011-09-06 14:39:44 +08:00
2013-03-28 17:35:22 +01:00
np = of_find_compatible_node ( NULL , NULL , " fsl,imx51-src " ) ;
if ( ! np )
return ;
2011-09-06 14:39:44 +08:00
src_base = of_iomap ( np , 0 ) ;
WARN_ON ( ! src_base ) ;
2011-12-09 00:51:26 +01:00
2013-03-28 17:35:19 +01:00
imx_reset_controller . of_node = np ;
2013-04-30 14:58:31 +02:00
if ( IS_ENABLED ( CONFIG_RESET_CONTROLLER ) )
reset_controller_register ( & imx_reset_controller ) ;
2013-03-28 17:35:19 +01:00
2011-12-09 00:51:26 +01:00
/*
* force warm reset sources to generate cold reset
* for a more reliable restart
*/
2013-03-28 17:35:19 +01:00
spin_lock ( & scr_lock ) ;
2011-12-09 00:51:26 +01:00
val = readl_relaxed ( src_base + SRC_SCR ) ;
val & = ~ ( 1 < < BP_SRC_SCR_WARM_RESET_ENABLE ) ;
writel_relaxed ( val , src_base + SRC_SCR ) ;
2013-03-28 17:35:19 +01:00
spin_unlock ( & scr_lock ) ;
2011-09-06 14:39:44 +08:00
}