2010-02-28 20:26:25 +03:00
/*
* Versatile Express Core Tile Cortex A9x4 Support
*/
# include <linux/init.h>
2010-03-29 21:52:45 +04:00
# include <linux/gfp.h>
2010-02-28 20:26:25 +03:00
# include <linux/device.h>
# include <linux/dma-mapping.h>
2010-04-15 13:16:26 +04:00
# include <linux/platform_device.h>
2010-02-28 20:26:25 +03:00
# include <linux/amba/bus.h>
# include <linux/amba/clcd.h>
2010-11-17 12:04:33 +03:00
# include <linux/clkdev.h>
2010-02-28 20:26:25 +03:00
# include <asm/hardware/arm_timer.h>
# include <asm/hardware/cache-l2x0.h>
# include <asm/hardware/gic.h>
2010-04-15 13:16:26 +04:00
# include <asm/pmu.h>
2011-02-28 19:01:04 +03:00
# include <asm/smp_scu.h>
2010-07-09 16:52:09 +04:00
# include <asm/smp_twd.h>
2010-02-28 20:26:25 +03:00
# include <mach/ct-ca9x4.h>
2010-10-06 19:18:08 +04:00
# include <asm/hardware/timer-sp.h>
2010-02-28 20:26:25 +03:00
# include <asm/mach/map.h>
# include <asm/mach/time.h>
# include "core.h"
# include <mach/motherboard.h>
2011-01-18 23:13:51 +03:00
# include <plat/clcd.h>
2010-02-28 20:26:25 +03:00
# define V2M_PA_CS7 0x10000000
static struct map_desc ct_ca9x4_io_desc [ ] __initdata = {
{
. virtual = __MMIO_P2V ( CT_CA9X4_MPIC ) ,
. pfn = __phys_to_pfn ( CT_CA9X4_MPIC ) ,
. length = SZ_16K ,
. type = MT_DEVICE ,
} , {
. virtual = __MMIO_P2V ( CT_CA9X4_SP804_TIMER ) ,
. pfn = __phys_to_pfn ( CT_CA9X4_SP804_TIMER ) ,
. length = SZ_4K ,
. type = MT_DEVICE ,
} , {
. virtual = __MMIO_P2V ( CT_CA9X4_L2CC ) ,
. pfn = __phys_to_pfn ( CT_CA9X4_L2CC ) ,
. length = SZ_4K ,
. type = MT_DEVICE ,
} ,
} ;
static void __init ct_ca9x4_map_io ( void )
{
2010-11-10 17:59:11 +03:00
# ifdef CONFIG_LOCAL_TIMERS
2010-07-09 16:52:09 +04:00
twd_base = MMIO_P2V ( A9_MPCORE_TWD ) ;
2010-11-10 17:59:11 +03:00
# endif
2011-02-28 19:01:04 +03:00
iotable_init ( ct_ca9x4_io_desc , ARRAY_SIZE ( ct_ca9x4_io_desc ) ) ;
2010-02-28 20:26:25 +03:00
}
static void __init ct_ca9x4_init_irq ( void )
{
2010-12-04 19:13:29 +03:00
gic_init ( 0 , 29 , MMIO_P2V ( A9_MPCORE_GIC_DIST ) ,
MMIO_P2V ( A9_MPCORE_GIC_CPU ) ) ;
2010-02-28 20:26:25 +03:00
}
#if 0
2010-10-05 14:29:28 +04:00
static void __init ct_ca9x4_timer_init ( void )
2010-02-28 20:26:25 +03:00
{
writel ( 0 , MMIO_P2V ( CT_CA9X4_TIMER0 ) + TIMER_CTRL ) ;
writel ( 0 , MMIO_P2V ( CT_CA9X4_TIMER1 ) + TIMER_CTRL ) ;
2011-05-12 15:08:23 +04:00
sp804_clocksource_init ( MMIO_P2V ( CT_CA9X4_TIMER1 ) , " ct-timer1 " ) ;
2011-05-12 18:31:13 +04:00
sp804_clockevents_init ( MMIO_P2V ( CT_CA9X4_TIMER0 ) , IRQ_CT_CA9X4_TIMER0 ,
" ct-timer0 " ) ;
2010-02-28 20:26:25 +03:00
}
static struct sys_timer ct_ca9x4_timer = {
. init = ct_ca9x4_timer_init ,
} ;
# endif
static void ct_ca9x4_clcd_enable ( struct clcd_fb * fb )
{
v2m_cfg_write ( SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1 , 0 ) ;
v2m_cfg_write ( SYS_CFG_DVIMODE | SYS_CFG_SITE_DB1 , 2 ) ;
}
static int ct_ca9x4_clcd_setup ( struct clcd_fb * fb )
{
unsigned long framesize = 1024 * 768 * 2 ;
2011-01-18 23:13:51 +03:00
fb - > panel = versatile_clcd_get_panel ( " XVGA " ) ;
if ( ! fb - > panel )
return - EINVAL ;
2010-02-28 20:26:25 +03:00
2011-01-18 23:13:51 +03:00
return versatile_clcd_setup_dma ( fb , framesize ) ;
2010-02-28 20:26:25 +03:00
}
static struct clcd_board ct_ca9x4_clcd_data = {
. name = " CT-CA9X4 " ,
2011-01-18 23:13:51 +03:00
. caps = CLCD_CAP_5551 | CLCD_CAP_565 ,
2010-02-28 20:26:25 +03:00
. check = clcdfb_check ,
. decode = clcdfb_decode ,
. enable = ct_ca9x4_clcd_enable ,
. setup = ct_ca9x4_clcd_setup ,
2011-01-18 23:13:51 +03:00
. mmap = versatile_clcd_mmap_dma ,
. remove = versatile_clcd_remove_dma ,
2010-02-28 20:26:25 +03:00
} ;
static AMBA_DEVICE ( clcd , " ct:clcd " , CT_CA9X4_CLCDC , & ct_ca9x4_clcd_data ) ;
static AMBA_DEVICE ( dmc , " ct:dmc " , CT_CA9X4_DMC , NULL ) ;
static AMBA_DEVICE ( smc , " ct:smc " , CT_CA9X4_SMC , NULL ) ;
static AMBA_DEVICE ( gpio , " ct:gpio " , CT_CA9X4_GPIO , NULL ) ;
static struct amba_device * ct_ca9x4_amba_devs [ ] __initdata = {
& clcd_device ,
& dmc_device ,
& smc_device ,
& gpio_device ,
} ;
static long ct_round ( struct clk * clk , unsigned long rate )
{
return rate ;
}
static int ct_set ( struct clk * clk , unsigned long rate )
{
return v2m_cfg_write ( SYS_CFG_OSC | SYS_CFG_SITE_DB1 | 1 , rate ) ;
}
static const struct clk_ops osc1_clk_ops = {
. round = ct_round ,
. set = ct_set ,
} ;
static struct clk osc1_clk = {
. ops = & osc1_clk_ops ,
. rate = 24000000 ,
} ;
2011-05-12 16:31:48 +04:00
static struct clk ct_sp804_clk = {
. rate = 1000000 ,
} ;
2010-02-28 20:26:25 +03:00
static struct clk_lookup lookups [ ] = {
{ /* CLCD */
. dev_id = " ct:clcd " ,
. clk = & osc1_clk ,
2011-05-12 18:45:16 +04:00
} , { /* SP804 timers */
. dev_id = " sp804 " ,
. con_id = " ct-timer0 " ,
. clk = & ct_sp804_clk ,
2011-05-12 16:31:48 +04:00
} , { /* SP804 timers */
. dev_id = " sp804 " ,
. con_id = " ct-timer1 " ,
. clk = & ct_sp804_clk ,
2010-02-28 20:26:25 +03:00
} ,
} ;
2010-04-15 13:16:26 +04: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 " ,
. id = ARM_PMU_DEVICE_CPU ,
. num_resources = ARRAY_SIZE ( pmu_resources ) ,
. resource = pmu_resources ,
} ;
2011-01-11 16:07:52 +03:00
static void __init ct_ca9x4_init_early ( void )
{
clkdev_add_table ( lookups , ARRAY_SIZE ( lookups ) ) ;
}
2010-10-05 14:29:28 +04:00
static void __init ct_ca9x4_init ( void )
2010-02-28 20:26:25 +03:00
{
int i ;
# ifdef CONFIG_CACHE_L2X0
2010-09-27 17:55:15 +04:00
void __iomem * l2x0_base = MMIO_P2V ( CT_CA9X4_L2CC ) ;
/* 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 20:26:25 +03: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 13:16:26 +04:00
platform_device_register ( & pmu_device ) ;
2010-02-28 20:26:25 +03:00
}
2011-02-28 19:01:04 +03:00
# ifdef CONFIG_SMP
static void ct_ca9x4_init_cpu_map ( void )
{
int i , ncores = scu_get_core_count ( MMIO_P2V ( A9_MPCORE_SCU ) ) ;
for ( i = 0 ; i < ncores ; + + i )
set_cpu_possible ( i , true ) ;
}
static void ct_ca9x4_smp_enable ( unsigned int max_cpus )
{
int i ;
for ( i = 0 ; i < max_cpus ; i + + )
set_cpu_present ( i , true ) ;
scu_enable ( MMIO_P2V ( A9_MPCORE_SCU ) ) ;
}
# endif
struct ct_desc ct_ca9x4_desc __initdata = {
. id = V2M_CT_ID_CA9 ,
. name = " CA9x4 " ,
2010-02-28 20:26:25 +03:00
. map_io = ct_ca9x4_map_io ,
2011-01-11 16:07:52 +03:00
. init_early = ct_ca9x4_init_early ,
2011-02-28 19:01:04 +03: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 20:26:25 +03:00
# endif
2011-02-28 19:01:04 +03:00
} ;