2011-12-27 11:18:36 +04:00
/*
2014-03-20 21:14:30 +04:00
* SAMSUNG EXYNOS Flattened Device Tree enabled machine
2011-12-27 11:18:36 +04:00
*
2014-03-20 21:14:30 +04:00
* Copyright ( c ) 2010 - 2014 Samsung Electronics Co . , Ltd .
* http : //www.samsung.com
2011-12-27 11:18:36 +04:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
2014-03-20 21:14:30 +04:00
# include <linux/init.h>
2011-12-27 11:18:36 +04:00
# include <linux/io.h>
2012-01-07 16:30:20 +04:00
# include <linux/of.h>
2012-05-15 11:25:23 +04:00
# include <linux/of_address.h>
2014-03-20 21:14:30 +04:00
# include <linux/of_fdt.h>
2013-08-30 14:15:04 +04:00
# include <linux/platform_device.h>
2014-07-11 03:08:29 +04:00
# include <linux/irqchip.h>
2015-12-18 06:32:11 +03:00
# include <linux/soc/samsung/exynos-regs-pmu.h>
2011-12-27 11:18:36 +04:00
2014-03-20 21:14:30 +04:00
# include <asm/cacheflush.h>
2011-12-27 11:18:36 +04:00
# include <asm/hardware/cache-l2x0.h>
2014-03-20 21:14:30 +04:00
# include <asm/mach/arch.h>
2011-12-27 11:18:36 +04:00
# include <asm/mach/map.h>
2015-01-08 19:14:23 +03:00
# include <mach/map.h>
2016-06-21 15:20:53 +03:00
# include <plat/cpu.h>
2015-01-08 19:14:23 +03:00
2011-12-27 11:18:36 +04:00
# include "common.h"
2013-12-18 23:06:56 +04:00
2012-02-11 17:15:45 +04:00
static struct map_desc exynos4_iodesc [ ] __initdata = {
{
2011-12-27 11:18:36 +04:00
. virtual = ( unsigned long ) S5P_VA_COREPERI_BASE ,
. pfn = __phys_to_pfn ( EXYNOS4_PA_COREPERI ) ,
. length = SZ_8K ,
. type = MT_DEVICE ,
} ,
} ;
2013-08-30 14:15:04 +04:00
static struct platform_device exynos_cpuidle = {
2014-05-09 01:56:29 +04:00
. name = " exynos_cpuidle " ,
2014-09-23 21:18:27 +04:00
# ifdef CONFIG_ARM_EXYNOS_CPUIDLE
2014-05-09 01:56:29 +04:00
. dev . platform_data = exynos_enter_aftr ,
2014-09-23 21:18:27 +04:00
# endif
2014-05-09 01:56:29 +04:00
. id = - 1 ,
2013-08-30 14:15:04 +04:00
} ;
2014-06-03 08:47:46 +04:00
void __iomem * sysram_base_addr ;
void __iomem * sysram_ns_base_addr ;
void __init exynos_sysram_init ( void )
{
struct device_node * node ;
for_each_compatible_node ( node , NULL , " samsung,exynos4210-sysram " ) {
if ( ! of_device_is_available ( node ) )
continue ;
sysram_base_addr = of_iomap ( node , 0 ) ;
break ;
}
for_each_compatible_node ( node , NULL , " samsung,exynos4210-sysram-ns " ) {
if ( ! of_device_is_available ( node ) )
continue ;
sysram_ns_base_addr = of_iomap ( node , 0 ) ;
break ;
}
}
2014-07-08 02:51:11 +04:00
static void __init exynos_init_late ( void )
2012-04-26 06:35:40 +04:00
{
2012-11-15 10:48:56 +04:00
if ( of_machine_is_compatible ( " samsung,exynos5440 " ) )
/* to be supported later */
return ;
2014-03-18 02:28:22 +04:00
exynos_pm_init ( ) ;
2012-04-26 06:35:40 +04:00
}
2013-06-18 20:36:56 +04:00
static int __init exynos_fdt_map_chipid ( unsigned long node , const char * uname ,
2013-04-23 17:46:53 +04:00
int depth , void * data )
{
struct map_desc iodesc ;
2014-05-05 13:26:48 +04:00
const __be32 * reg ;
2014-04-02 08:49:03 +04:00
int len ;
2013-04-23 17:46:53 +04:00
if ( ! of_flat_dt_is_compatible ( node , " samsung,exynos4210-chipid " ) & &
! of_flat_dt_is_compatible ( node , " samsung,exynos5440-clock " ) )
return 0 ;
reg = of_get_flat_dt_prop ( node , " reg " , & len ) ;
if ( reg = = NULL | | len ! = ( sizeof ( unsigned long ) * 2 ) )
return 0 ;
iodesc . pfn = __phys_to_pfn ( be32_to_cpu ( reg [ 0 ] ) ) ;
iodesc . length = be32_to_cpu ( reg [ 1 ] ) - 1 ;
iodesc . virtual = ( unsigned long ) S5P_VA_CHIPID ;
iodesc . type = MT_DEVICE ;
iotable_init ( & iodesc , 1 ) ;
return 1 ;
}
2011-12-27 11:18:36 +04:00
/*
* exynos_map_io
*
* register the standard cpu IO areas
*/
2014-03-20 21:09:39 +04:00
static void __init exynos_map_io ( void )
{
2014-03-20 21:14:30 +04:00
if ( soc_is_exynos4 ( ) )
2014-03-20 21:09:39 +04:00
iotable_init ( exynos4_iodesc , ARRAY_SIZE ( exynos4_iodesc ) ) ;
}
2011-12-27 11:18:36 +04:00
2014-07-08 02:51:11 +04:00
static void __init exynos_init_io ( void )
2011-12-27 11:18:36 +04:00
{
2013-06-06 00:56:33 +04:00
debug_ll_io_init ( ) ;
2013-06-15 04:13:25 +04:00
of_scan_flat_dt ( exynos_fdt_map_chipid , NULL ) ;
2012-11-15 10:48:56 +04:00
2011-12-27 11:18:36 +04:00
/* detect cpu id and rev. */
s5p_init_cpu ( S5P_VA_CHIPID ) ;
2014-03-20 21:09:39 +04:00
exynos_map_io ( ) ;
2012-02-11 17:15:45 +04:00
}
2015-03-11 13:13:57 +03:00
/*
* Set or clear the USE_DELAYED_RESET_ASSERTION option . Used by smp code
* and suspend .
*
* This is necessary only on Exynos4 SoCs . When system is running
* USE_DELAYED_RESET_ASSERTION should be set so the ARM CLK clock down
* feature could properly detect global idle state when secondary CPU is
* powered down .
*
* However this should not be set when such system is going into suspend .
*/
void exynos_set_delayed_reset_assertion ( bool enable )
{
2015-05-14 05:43:59 +03:00
if ( of_machine_is_compatible ( " samsung,exynos4 " ) ) {
2015-03-11 13:13:57 +03:00
unsigned int tmp , core_id ;
for ( core_id = 0 ; core_id < num_possible_cpus ( ) ; core_id + + ) {
tmp = pmu_raw_readl ( EXYNOS_ARM_CORE_OPTION ( core_id ) ) ;
if ( enable )
tmp | = S5P_USE_DELAYED_RESET_ASSERTION ;
else
tmp & = ~ ( S5P_USE_DELAYED_RESET_ASSERTION ) ;
pmu_raw_writel ( tmp , EXYNOS_ARM_CORE_OPTION ( core_id ) ) ;
}
}
}
2015-03-11 18:44:52 +03:00
/*
* Apparently , these SoCs are not able to wake - up from suspend using
* the PMU . Too bad . Should they suddenly become capable of such a
* feat , the matches below should be moved to suspend . c .
*/
2014-07-11 03:08:29 +04:00
static const struct of_device_id exynos_dt_pmu_match [ ] = {
2014-07-29 01:17:39 +04:00
{ . compatible = " samsung,exynos5260-pmu " } ,
2014-07-29 01:10:40 +04:00
{ . compatible = " samsung,exynos5410-pmu " } ,
2014-07-11 03:08:29 +04:00
{ /*sentinel*/ } ,
} ;
static void exynos_map_pmu ( void )
{
struct device_node * np ;
np = of_find_matching_node ( NULL , exynos_dt_pmu_match ) ;
if ( np )
pmu_base_addr = of_iomap ( np , 0 ) ;
}
static void __init exynos_init_irq ( void )
{
irqchip_init ( ) ;
/*
* Since platsmp . c needs pmu base address by the time
* DT is not unflatten so we can ' t use DT APIs before
* init_irq
*/
exynos_map_pmu ( ) ;
}
2014-03-20 21:14:30 +04:00
static void __init exynos_dt_machine_init ( void )
2011-12-27 11:18:36 +04:00
{
2014-06-03 08:47:46 +04:00
/*
* This is called from smp_prepare_cpus if we ' ve built for SMP , but
* we still need to set it up for PM and firmware ops if not .
*/
2014-07-05 01:09:18 +04:00
if ( ! IS_ENABLED ( CONFIG_SMP ) )
2014-06-03 08:47:46 +04:00
exynos_sysram_init ( ) ;
2015-03-17 21:26:11 +03:00
# if defined(CONFIG_SMP) && defined(CONFIG_ARM_EXYNOS_CPUIDLE)
2015-03-18 16:09:57 +03:00
if ( of_machine_is_compatible ( " samsung,exynos4210 " ) | |
of_machine_is_compatible ( " samsung,exynos3250 " ) )
2015-01-24 08:05:50 +03:00
exynos_cpuidle . dev . platform_data = & cpuidle_coupled_exynos_data ;
# endif
2014-07-18 22:48:35 +04:00
if ( of_machine_is_compatible ( " samsung,exynos4210 " ) | |
2014-09-25 12:59:41 +04:00
of_machine_is_compatible ( " samsung,exynos4212 " ) | |
( of_machine_is_compatible ( " samsung,exynos4412 " ) & &
of_machine_is_compatible ( " samsung,trats2 " ) ) | |
2015-03-26 20:35:52 +03:00
of_machine_is_compatible ( " samsung,exynos3250 " ) | |
2014-09-25 12:59:41 +04:00
of_machine_is_compatible ( " samsung,exynos5250 " ) )
2014-07-18 22:48:35 +04:00
platform_device_register ( & exynos_cpuidle ) ;
2011-12-27 11:18:36 +04:00
}
2014-03-20 21:14:30 +04:00
2015-02-18 23:01:45 +03:00
static char const * const exynos_dt_compat [ ] __initconst = {
2014-05-25 23:12:26 +04:00
" samsung,exynos3 " ,
" samsung,exynos3250 " ,
2014-03-20 21:14:59 +04:00
" samsung,exynos4 " ,
2014-03-20 21:14:30 +04:00
" samsung,exynos4210 " ,
" samsung,exynos4212 " ,
" samsung,exynos4412 " ,
2014-11-07 02:20:09 +03:00
" samsung,exynos4415 " ,
2014-03-20 21:14:59 +04:00
" samsung,exynos5 " ,
2014-03-20 21:14:30 +04:00
" samsung,exynos5250 " ,
2014-05-25 23:28:17 +04:00
" samsung,exynos5260 " ,
2014-03-20 21:14:30 +04:00
" samsung,exynos5420 " ,
" samsung,exynos5440 " ,
NULL
} ;
2014-07-15 21:03:36 +04:00
static void __init exynos_dt_fixup ( void )
{
/*
* Some versions of uboot pass garbage entries in the memory node ,
* use the old CONFIG_ARM_NR_BANKS
*/
of_fdt_limit_memory ( 8 ) ;
}
2014-03-20 21:14:30 +04:00
DT_MACHINE_START ( EXYNOS_DT , " SAMSUNG EXYNOS (Flattened Device Tree) " )
/* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
2014-04-28 18:54:08 +04:00
. l2c_aux_val = 0x3c400001 ,
. l2c_aux_mask = 0xc20fffff ,
2014-03-20 21:14:30 +04:00
. smp = smp_ops ( exynos_smp_ops ) ,
. map_io = exynos_init_io ,
. init_early = exynos_firmware_init ,
2014-07-11 03:08:29 +04:00
. init_irq = exynos_init_irq ,
2014-03-20 21:14:30 +04:00
. init_machine = exynos_dt_machine_init ,
. init_late = exynos_init_late ,
. dt_compat = exynos_dt_compat ,
2014-07-15 21:03:36 +04:00
. dt_fixup = exynos_dt_fixup ,
2014-03-20 21:14:30 +04:00
MACHINE_END