2017-12-25 20:54:31 +01:00
// SPDX-License-Identifier: GPL-2.0
//
// SAMSUNG EXYNOS Flattened Device Tree enabled machine
//
// Copyright (c) 2010-2014 Samsung Electronics Co., Ltd.
// http://www.samsung.com
2011-12-27 08:18:36 +01:00
2014-03-21 02:14:30 +09:00
# include <linux/init.h>
2011-12-27 08:18:36 +01:00
# include <linux/io.h>
2012-01-07 12:30:20 +00:00
# include <linux/of.h>
2012-05-15 16:25:23 +09:00
# include <linux/of_address.h>
2014-03-21 02:14:30 +09:00
# include <linux/of_fdt.h>
2013-08-30 12:15:04 +02:00
# include <linux/platform_device.h>
2014-07-11 08:08:29 +09:00
# include <linux/irqchip.h>
2015-12-18 09:02:11 +05:30
# include <linux/soc/samsung/exynos-regs-pmu.h>
2011-12-27 08:18:36 +01:00
2014-03-21 02:14:30 +09:00
# include <asm/cacheflush.h>
2011-12-27 08:18:36 +01:00
# include <asm/hardware/cache-l2x0.h>
2014-03-21 02:14:30 +09:00
# include <asm/mach/arch.h>
2011-12-27 08:18:36 +01:00
# include <asm/mach/map.h>
2015-01-09 01:14:23 +09:00
# include <mach/map.h>
2016-06-21 13:20:53 +01:00
# include <plat/cpu.h>
2015-01-09 01:14:23 +09:00
2011-12-27 08:18:36 +01:00
# include "common.h"
2013-12-19 04:06:56 +09:00
2013-08-30 12:15:04 +02:00
static struct platform_device exynos_cpuidle = {
2014-05-09 06:56:29 +09:00
. name = " exynos_cpuidle " ,
2014-09-24 02:18:27 +09:00
# ifdef CONFIG_ARM_EXYNOS_CPUIDLE
2014-05-09 06:56:29 +09:00
. dev . platform_data = exynos_enter_aftr ,
2014-09-24 02:18:27 +09:00
# endif
2014-05-09 06:56:29 +09:00
. id = - 1 ,
2013-08-30 12:15:04 +02:00
} ;
2016-12-10 15:47:33 +02:00
void __iomem * sysram_base_addr __ro_after_init ;
void __iomem * sysram_ns_base_addr __ro_after_init ;
2014-06-02 21:47:46 -07:00
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 ;
}
}
2013-06-19 01:36:56 +09:00
static int __init exynos_fdt_map_chipid ( unsigned long node , const char * uname ,
2013-04-23 22:46:53 +09:00
int depth , void * data )
{
struct map_desc iodesc ;
2014-05-05 14:56:48 +05:30
const __be32 * reg ;
2014-04-01 23:49:03 -05:00
int len ;
2013-04-23 22:46:53 +09:00
2018-04-24 22:32:39 +02:00
if ( ! of_flat_dt_is_compatible ( node , " samsung,exynos4210-chipid " ) )
2013-04-23 22:46:53 +09:00
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 ;
}
2014-07-08 07:51:11 +09:00
static void __init exynos_init_io ( void )
2011-12-27 08:18:36 +01:00
{
2013-06-05 13:56:33 -07:00
debug_ll_io_init ( ) ;
2013-06-15 09:13:25 +09:00
of_scan_flat_dt ( exynos_fdt_map_chipid , NULL ) ;
2012-11-15 15:48:56 +09:00
2011-12-27 08:18:36 +01:00
/* detect cpu id and rev. */
s5p_init_cpu ( S5P_VA_CHIPID ) ;
2012-02-11 22:15:45 +09:00
}
2015-03-11 11:13:57 +01: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 11:43:59 +09:00
if ( of_machine_is_compatible ( " samsung,exynos4 " ) ) {
2015-03-11 11:13:57 +01: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 15:44:52 +00: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 08:08:29 +09:00
static const struct of_device_id exynos_dt_pmu_match [ ] = {
2014-07-29 06:17:39 +09:00
{ . compatible = " samsung,exynos5260-pmu " } ,
2014-07-29 06:10:40 +09:00
{ . compatible = " samsung,exynos5410-pmu " } ,
2014-07-11 08:08:29 +09: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-21 02:14:30 +09:00
static void __init exynos_dt_machine_init ( void )
2011-12-27 08:18:36 +01:00
{
2014-06-02 21:47:46 -07: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 06:09:18 +09:00
if ( ! IS_ENABLED ( CONFIG_SMP ) )
2014-06-02 21:47:46 -07:00
exynos_sysram_init ( ) ;
2015-03-18 03:26:11 +09:00
# if defined(CONFIG_SMP) && defined(CONFIG_ARM_EXYNOS_CPUIDLE)
2015-03-18 14:09:57 +01:00
if ( of_machine_is_compatible ( " samsung,exynos4210 " ) | |
of_machine_is_compatible ( " samsung,exynos3250 " ) )
2015-01-24 14:05:50 +09:00
exynos_cpuidle . dev . platform_data = & cpuidle_coupled_exynos_data ;
# endif
2014-07-19 03:48:35 +09:00
if ( of_machine_is_compatible ( " samsung,exynos4210 " ) | |
2014-09-25 17:59:41 +09:00
( of_machine_is_compatible ( " samsung,exynos4412 " ) & &
2018-02-19 00:41:24 +11:00
( of_machine_is_compatible ( " samsung,trats2 " ) | |
of_machine_is_compatible ( " samsung,midas " ) ) ) | |
2015-03-27 02:35:52 +09:00
of_machine_is_compatible ( " samsung,exynos3250 " ) | |
2014-09-25 17:59:41 +09:00
of_machine_is_compatible ( " samsung,exynos5250 " ) )
2014-07-19 03:48:35 +09:00
platform_device_register ( & exynos_cpuidle ) ;
2011-12-27 08:18:36 +01:00
}
2014-03-21 02:14:30 +09:00
2015-02-18 21:01:45 +01:00
static char const * const exynos_dt_compat [ ] __initconst = {
2014-05-26 04:12:26 +09:00
" samsung,exynos3 " ,
" samsung,exynos3250 " ,
2014-03-21 02:14:59 +09:00
" samsung,exynos4 " ,
2014-03-21 02:14:30 +09:00
" samsung,exynos4210 " ,
" samsung,exynos4412 " ,
2014-03-21 02:14:59 +09:00
" samsung,exynos5 " ,
2014-03-21 02:14:30 +09:00
" samsung,exynos5250 " ,
2014-05-26 04:28:17 +09:00
" samsung,exynos5260 " ,
2014-03-21 02:14:30 +09:00
" samsung,exynos5420 " ,
NULL
} ;
2014-07-15 10:03:36 -07: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-21 02:14:30 +09: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 15:54:08 +01:00
. l2c_aux_val = 0x3c400001 ,
. l2c_aux_mask = 0xc20fffff ,
2014-03-21 02:14:30 +09:00
. smp = smp_ops ( exynos_smp_ops ) ,
. map_io = exynos_init_io ,
. init_early = exynos_firmware_init ,
2014-07-11 08:08:29 +09:00
. init_irq = exynos_init_irq ,
2014-03-21 02:14:30 +09:00
. init_machine = exynos_dt_machine_init ,
2018-04-24 22:32:39 +02:00
. init_late = exynos_pm_init ,
2014-03-21 02:14:30 +09:00
. dt_compat = exynos_dt_compat ,
2014-07-15 10:03:36 -07:00
. dt_fixup = exynos_dt_fixup ,
2014-03-21 02:14:30 +09:00
MACHINE_END