2010-02-28 17:26:25 +00:00
/*
* Versatile Express Core Tile Cortex A9x4 Support
*/
# include <linux/init.h>
2010-03-30 02:52:45 +09:00
# include <linux/gfp.h>
2010-02-28 17:26:25 +00:00
# include <linux/device.h>
# include <linux/dma-mapping.h>
2010-04-15 10:16:26 +01:00
# include <linux/platform_device.h>
2010-02-28 17:26:25 +00:00
# include <linux/amba/bus.h>
# include <linux/amba/clcd.h>
2010-11-17 10:04:33 +01:00
# include <linux/clkdev.h>
2012-10-09 12:56:36 +01:00
# include <linux/vexpress.h>
2012-12-27 13:10:24 -06:00
# include <linux/irqchip/arm-gic.h>
2010-02-28 17:26:25 +00:00
# include <asm/hardware/arm_timer.h>
# include <asm/hardware/cache-l2x0.h>
2011-02-28 17:01:04 +01:00
# include <asm/smp_scu.h>
2010-07-09 13:52:09 +01:00
# include <asm/smp_twd.h>
2010-02-28 17:26:25 +00:00
# include <mach/ct-ca9x4.h>
2010-10-06 16:18:08 +01:00
# include <asm/hardware/timer-sp.h>
2010-02-28 17:26:25 +00:00
# include <asm/mach/map.h>
# include <asm/mach/time.h>
# include "core.h"
# include <mach/motherboard.h>
2012-05-07 16:54:40 +00:00
# include <mach/irqs.h>
2010-02-28 17:26:25 +00:00
2011-01-18 20:13:51 +00:00
# include <plat/clcd.h>
2010-02-28 17:26:25 +00:00
static struct map_desc ct_ca9x4_io_desc [ ] __initdata = {
{
2012-01-25 15:37:29 +00:00
. virtual = V2T_PERIPH ,
. pfn = __phys_to_pfn ( CT_CA9X4_MPIC ) ,
. length = SZ_8K ,
. type = MT_DEVICE ,
2010-02-28 17:26:25 +00:00
} ,
} ;
static void __init ct_ca9x4_map_io ( void )
{
2012-01-25 15:37:29 +00:00
iotable_init ( ct_ca9x4_io_desc , ARRAY_SIZE ( ct_ca9x4_io_desc ) ) ;
2010-02-28 17:26:25 +00:00
}
2011-08-04 11:57:04 +01:00
# ifdef CONFIG_HAVE_ARM_TWD
static DEFINE_TWD_LOCAL_TIMER ( twd_local_timer , A9_MPCORE_TWD , IRQ_LOCALTIMER ) ;
static void __init ca9x4_twd_init ( void )
{
int err = twd_local_timer_register ( & twd_local_timer ) ;
if ( err )
pr_err ( " twd_local_timer_register failed %d \n " , err ) ;
}
# else
# define ca9x4_twd_init() do {} while(0)
# endif
2010-02-28 17:26:25 +00:00
static void __init ct_ca9x4_init_irq ( void )
{
2012-01-25 15:37:29 +00:00
gic_init ( 0 , 29 , ioremap ( A9_MPCORE_GIC_DIST , SZ_4K ) ,
ioremap ( A9_MPCORE_GIC_CPU , SZ_256 ) ) ;
2011-08-04 11:57:04 +01:00
ca9x4_twd_init ( ) ;
2010-02-28 17:26:25 +00:00
}
static int ct_ca9x4_clcd_setup ( struct clcd_fb * fb )
{
unsigned long framesize = 1024 * 768 * 2 ;
2011-01-18 20:13:51 +00:00
fb - > panel = versatile_clcd_get_panel ( " XVGA " ) ;
if ( ! fb - > panel )
return - EINVAL ;
2010-02-28 17:26:25 +00:00
2011-01-18 20:13:51 +00:00
return versatile_clcd_setup_dma ( fb , framesize ) ;
2010-02-28 17:26:25 +00:00
}
static struct clcd_board ct_ca9x4_clcd_data = {
. name = " CT-CA9X4 " ,
2011-01-18 20:13:51 +00:00
. caps = CLCD_CAP_5551 | CLCD_CAP_565 ,
2010-02-28 17:26:25 +00:00
. check = clcdfb_check ,
. decode = clcdfb_decode ,
. setup = ct_ca9x4_clcd_setup ,
2011-01-18 20:13:51 +00:00
. mmap = versatile_clcd_mmap_dma ,
. remove = versatile_clcd_remove_dma ,
2010-02-28 17:26:25 +00:00
} ;
2011-12-18 12:07:09 +00:00
static AMBA_AHB_DEVICE ( clcd , " ct:clcd " , 0 , CT_CA9X4_CLCDC , IRQ_CT_CA9X4_CLCDC , & ct_ca9x4_clcd_data ) ;
static AMBA_APB_DEVICE ( dmc , " ct:dmc " , 0 , CT_CA9X4_DMC , IRQ_CT_CA9X4_DMC , NULL ) ;
static AMBA_APB_DEVICE ( smc , " ct:smc " , 0 , CT_CA9X4_SMC , IRQ_CT_CA9X4_SMC , NULL ) ;
static AMBA_APB_DEVICE ( gpio , " ct:gpio " , 0 , CT_CA9X4_GPIO , IRQ_CT_CA9X4_GPIO , NULL ) ;
2010-02-28 17:26:25 +00:00
static struct amba_device * ct_ca9x4_amba_devs [ ] __initdata = {
& clcd_device ,
& dmc_device ,
& smc_device ,
& gpio_device ,
} ;
2010-04-15 10:16:26 +01:00
static struct resource pmu_resources [ ] = {
[ 0 ] = {
. start = IRQ_CT_CA9X4_PMU_CPU0 ,
. end = IRQ_CT_CA9X4_PMU_CPU0 ,
. flags = IORESOURCE_IRQ ,
} ,
[ 1 ] = {
. start = IRQ_CT_CA9X4_PMU_CPU1 ,
. end = IRQ_CT_CA9X4_PMU_CPU1 ,
. flags = IORESOURCE_IRQ ,
} ,
[ 2 ] = {
. start = IRQ_CT_CA9X4_PMU_CPU2 ,
. end = IRQ_CT_CA9X4_PMU_CPU2 ,
. flags = IORESOURCE_IRQ ,
} ,
[ 3 ] = {
. start = IRQ_CT_CA9X4_PMU_CPU3 ,
. end = IRQ_CT_CA9X4_PMU_CPU3 ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct platform_device pmu_device = {
. name = " arm-pmu " ,
2012-07-19 09:50:21 +01:00
. id = - 1 ,
2010-04-15 10:16:26 +01:00
. num_resources = ARRAY_SIZE ( pmu_resources ) ,
. resource = pmu_resources ,
} ;
2012-10-09 12:56:36 +01:00
static struct platform_device osc1_device = {
. name = " vexpress-osc " ,
. id = 1 ,
. num_resources = 1 ,
. resource = ( struct resource [ ] ) {
VEXPRESS_RES_FUNC ( 0xf , 1 ) ,
} ,
} ;
2010-10-05 11:29:28 +01:00
static void __init ct_ca9x4_init ( void )
2010-02-28 17:26:25 +00:00
{
int i ;
# ifdef CONFIG_CACHE_L2X0
2012-01-25 15:37:29 +00:00
void __iomem * l2x0_base = ioremap ( CT_CA9X4_L2CC , SZ_4K ) ;
2010-09-27 14:55:15 +01:00
/* set RAM latencies to 1 cycle for this core tile. */
writel ( 0 , l2x0_base + L2X0_TAG_LATENCY_CTRL ) ;
writel ( 0 , l2x0_base + L2X0_DATA_LATENCY_CTRL ) ;
l2x0_init ( l2x0_base , 0x00400000 , 0xfe0fffff ) ;
2010-02-28 17:26:25 +00:00
# endif
for ( i = 0 ; i < ARRAY_SIZE ( ct_ca9x4_amba_devs ) ; i + + )
amba_device_register ( ct_ca9x4_amba_devs [ i ] , & iomem_resource ) ;
2010-04-15 10:16:26 +01:00
platform_device_register ( & pmu_device ) ;
2012-10-09 12:56:36 +01:00
platform_device_register ( & osc1_device ) ;
WARN_ON ( clk_register_clkdev ( vexpress_osc_setup ( & osc1_device . dev ) ,
NULL , " ct:clcd " ) ) ;
2010-02-28 17:26:25 +00:00
}
2011-02-28 17:01:04 +01:00
# ifdef CONFIG_SMP
2012-01-25 15:37:29 +00:00
static void * ct_ca9x4_scu_base __initdata ;
2012-01-18 19:40:13 +00:00
static void __init ct_ca9x4_init_cpu_map ( void )
2011-02-28 17:01:04 +01:00
{
2012-01-25 15:37:29 +00:00
int i , ncores ;
ct_ca9x4_scu_base = ioremap ( A9_MPCORE_SCU , SZ_128 ) ;
if ( WARN_ON ( ! ct_ca9x4_scu_base ) )
return ;
ncores = scu_get_core_count ( ct_ca9x4_scu_base ) ;
2011-02-28 17:01:04 +01:00
2011-10-20 22:04:18 +01:00
if ( ncores > nr_cpu_ids ) {
pr_warn ( " SMP: %u cores greater than maximum (%u), clipping \n " ,
ncores , nr_cpu_ids ) ;
ncores = nr_cpu_ids ;
}
2011-02-28 17:01:04 +01:00
for ( i = 0 ; i < ncores ; + + i )
set_cpu_possible ( i , true ) ;
}
2012-01-18 19:40:13 +00:00
static void __init ct_ca9x4_smp_enable ( unsigned int max_cpus )
2011-02-28 17:01:04 +01:00
{
2012-01-25 15:37:29 +00:00
scu_enable ( ct_ca9x4_scu_base ) ;
2011-02-28 17:01:04 +01:00
}
# endif
struct ct_desc ct_ca9x4_desc __initdata = {
. id = V2M_CT_ID_CA9 ,
. name = " CA9x4 " ,
2010-02-28 17:26:25 +00:00
. map_io = ct_ca9x4_map_io ,
2011-02-28 17:01:04 +01:00
. init_irq = ct_ca9x4_init_irq ,
. init_tile = ct_ca9x4_init ,
# ifdef CONFIG_SMP
. init_cpu_map = ct_ca9x4_init_cpu_map ,
. smp_enable = ct_ca9x4_smp_enable ,
2010-02-28 17:26:25 +00:00
# endif
2011-02-28 17:01:04 +01:00
} ;