2019-05-29 07:17:56 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2011-06-20 11:47:27 -06:00
/*
* This file contains common code that is intended to be used across
* boards so that it ' s not replicated .
*
* Copyright ( C ) 2011 Xilinx
*/
# include <linux/init.h>
2019-04-18 15:20:22 -07:00
# include <linux/io.h>
2011-06-20 11:47:27 -06:00
# include <linux/kernel.h>
# include <linux/cpumask.h>
# include <linux/platform_device.h>
# include <linux/clk.h>
2012-11-08 12:04:26 -06:00
# include <linux/clk/zynq.h>
2013-03-20 10:15:28 +01:00
# include <linux/clocksource.h>
2012-11-08 12:04:26 -06:00
# include <linux/of_address.h>
2020-02-12 11:08:30 +01:00
# include <linux/of_clk.h>
2011-06-20 11:47:27 -06:00
# include <linux/of_irq.h>
# include <linux/of_platform.h>
2011-07-07 11:35:20 +00:00
# include <linux/of.h>
2014-01-31 12:55:06 +01:00
# include <linux/memblock.h>
2013-10-31 09:10:18 -07:00
# include <linux/irqchip.h>
# include <linux/irqchip/arm-gic.h>
2013-07-31 09:19:59 +02:00
# include <linux/slab.h>
# include <linux/sys_soc.h>
2020-06-08 21:32:42 -07:00
# include <linux/pgtable.h>
2011-06-20 11:47:27 -06:00
2011-07-07 11:35:20 +00:00
# include <asm/mach/arch.h>
2011-06-20 11:47:27 -06:00
# include <asm/mach/map.h>
2012-10-31 11:11:59 -06:00
# include <asm/mach/time.h>
2011-07-07 11:35:20 +00:00
# include <asm/mach-types.h>
2011-06-20 11:47:27 -06:00
# include <asm/page.h>
2013-03-20 11:11:43 +01:00
# include <asm/smp_scu.h>
2013-07-31 09:19:59 +02:00
# include <asm/system_info.h>
2011-06-20 11:47:27 -06:00
# include <asm/hardware/cache-l2x0.h>
# include "common.h"
2013-07-31 09:19:59 +02:00
# define ZYNQ_DEVCFG_MCTRL 0x80
# define ZYNQ_DEVCFG_PS_VERSION_SHIFT 28
# define ZYNQ_DEVCFG_PS_VERSION_MASK 0xF
2013-03-20 11:11:43 +01:00
void __iomem * zynq_scu_base ;
2014-01-31 12:55:06 +01:00
/**
* zynq_memory_init - Initialize special memory
*
* We need to stop things allocating the low memory as DMA can ' t work in
* the 1 st 512 K of memory .
*/
static void __init zynq_memory_init ( void )
{
if ( ! __pa ( PAGE_OFFSET ) )
2016-10-31 11:26:17 -05:00
memblock_reserve ( __pa ( PAGE_OFFSET ) , 0x80000 ) ;
2014-01-31 12:55:06 +01:00
}
2013-09-21 18:41:02 +02:00
static struct platform_device zynq_cpuidle_device = {
. name = " cpuidle-zynq " ,
} ;
2013-07-31 09:19:59 +02:00
/**
* zynq_get_revision - Get Zynq silicon revision
*
* Return : Silicon version or - 1 otherwise
*/
static int __init zynq_get_revision ( void )
{
struct device_node * np ;
void __iomem * zynq_devcfg_base ;
u32 revision ;
np = of_find_compatible_node ( NULL , NULL , " xlnx,zynq-devcfg-1.0 " ) ;
if ( ! np ) {
pr_err ( " %s: no devcfg node found \n " , __func__ ) ;
return - 1 ;
}
zynq_devcfg_base = of_iomap ( np , 0 ) ;
2022-06-05 12:28:07 +04:00
of_node_put ( np ) ;
2013-07-31 09:19:59 +02:00
if ( ! zynq_devcfg_base ) {
pr_err ( " %s: Unable to map I/O memory \n " , __func__ ) ;
return - 1 ;
}
revision = readl ( zynq_devcfg_base + ZYNQ_DEVCFG_MCTRL ) ;
revision > > = ZYNQ_DEVCFG_PS_VERSION_SHIFT ;
revision & = ZYNQ_DEVCFG_PS_VERSION_MASK ;
iounmap ( zynq_devcfg_base ) ;
return revision ;
}
2014-09-02 14:19:06 -07:00
static void __init zynq_init_late ( void )
{
zynq_core_pm_init ( ) ;
2014-09-02 14:19:09 -07:00
zynq_pm_late_init ( ) ;
2014-09-02 14:19:06 -07:00
}
2011-06-20 11:47:27 -06:00
/**
2013-03-27 13:07:00 +01:00
* zynq_init_machine - System specific initialization , intended to be
* called from board specific initialization .
2011-06-20 11:47:27 -06:00
*/
2013-03-27 13:07:00 +01:00
static void __init zynq_init_machine ( void )
2011-06-20 11:47:27 -06:00
{
2013-07-31 09:19:59 +02:00
struct soc_device_attribute * soc_dev_attr ;
struct soc_device * soc_dev ;
struct device * parent = NULL ;
2014-02-19 15:14:44 -08:00
2013-07-31 09:19:59 +02:00
soc_dev_attr = kzalloc ( sizeof ( * soc_dev_attr ) , GFP_KERNEL ) ;
if ( ! soc_dev_attr )
goto out ;
system_rev = zynq_get_revision ( ) ;
soc_dev_attr - > family = kasprintf ( GFP_KERNEL , " Xilinx Zynq " ) ;
soc_dev_attr - > revision = kasprintf ( GFP_KERNEL , " 0x%x " , system_rev ) ;
soc_dev_attr - > soc_id = kasprintf ( GFP_KERNEL , " 0x%x " ,
zynq_slcr_get_device_id ( ) ) ;
soc_dev = soc_device_register ( soc_dev_attr ) ;
if ( IS_ERR ( soc_dev ) ) {
kfree ( soc_dev_attr - > family ) ;
kfree ( soc_dev_attr - > revision ) ;
kfree ( soc_dev_attr - > soc_id ) ;
kfree ( soc_dev_attr ) ;
goto out ;
}
parent = soc_device_to_device ( soc_dev ) ;
out :
/*
* Finished with the static registrations now ; fill in the missing
* devices
*/
2016-06-01 14:53:05 +08:00
of_platform_default_populate ( NULL , NULL , parent ) ;
2013-09-21 18:41:02 +02:00
platform_device_register ( & zynq_cpuidle_device ) ;
2011-06-20 11:47:27 -06:00
}
2013-03-27 13:07:00 +01:00
static void __init zynq_timer_init ( void )
2012-10-31 11:11:59 -06:00
{
2013-11-18 16:48:19 +01:00
zynq_clock_init ( ) ;
2014-02-05 15:41:51 +01:00
of_clk_init ( NULL ) ;
2017-05-26 17:40:46 +02:00
timer_probe ( ) ;
2012-10-31 11:11:59 -06:00
}
2013-03-20 11:11:43 +01:00
static struct map_desc zynq_cortex_a9_scu_map __initdata = {
. length = SZ_256 ,
. type = MT_DEVICE ,
} ;
static void __init zynq_scu_map_io ( void )
{
unsigned long base ;
base = scu_a9_get_base ( ) ;
zynq_cortex_a9_scu_map . pfn = __phys_to_pfn ( base ) ;
/* Expected address is in vmalloc area that's why simple assign here */
zynq_cortex_a9_scu_map . virtual = base ;
iotable_init ( & zynq_cortex_a9_scu_map , 1 ) ;
zynq_scu_base = ( void __iomem * ) base ;
BUG_ON ( ! zynq_scu_base ) ;
}
2011-06-20 11:47:27 -06:00
/**
2013-03-27 13:07:00 +01:00
* zynq_map_io - Create memory mappings needed for early I / O .
2011-06-20 11:47:27 -06:00
*/
2013-03-27 13:07:00 +01:00
static void __init zynq_map_io ( void )
2011-06-20 11:47:27 -06:00
{
2012-11-19 10:16:01 -06:00
debug_ll_io_init ( ) ;
2013-03-20 11:11:43 +01:00
zynq_scu_map_io ( ) ;
2011-06-20 11:47:27 -06:00
}
2011-07-07 11:35:20 +00:00
2013-10-31 09:10:18 -07:00
static void __init zynq_irq_init ( void )
{
2016-02-02 20:30:48 -06:00
zynq_early_slcr_init ( ) ;
2013-10-31 09:10:18 -07:00
irqchip_init ( ) ;
}
2013-03-27 13:07:00 +01:00
static const char * const zynq_dt_match [ ] = {
2012-10-31 12:24:48 -06:00
" xlnx,zynq-7000 " ,
2011-07-07 11:35:20 +00:00
NULL
} ;
2013-06-13 14:13:37 +02:00
DT_MACHINE_START ( XILINX_EP107 , " Xilinx Zynq Platform " )
2014-04-28 15:31:11 +01:00
/* 64KB way size, 8-way associativity, parity disabled */
2015-05-12 08:22:01 +02:00
. l2c_aux_val = 0x00400000 ,
. l2c_aux_mask = 0xffbfffff ,
2013-03-20 13:50:12 +01:00
. smp = smp_ops ( zynq_smp_ops ) ,
2013-03-27 13:07:00 +01:00
. map_io = zynq_map_io ,
2013-10-31 09:10:18 -07:00
. init_irq = zynq_irq_init ,
2013-03-27 13:07:00 +01:00
. init_machine = zynq_init_machine ,
2014-09-02 14:19:06 -07:00
. init_late = zynq_init_late ,
2013-03-27 13:07:00 +01:00
. init_time = zynq_timer_init ,
. dt_compat = zynq_dt_match ,
2014-01-31 12:55:06 +01:00
. reserve = zynq_memory_init ,
2011-07-07 11:35:20 +00:00
MACHINE_END