2010-02-11 21:44:53 +00:00
/*
* Versatile Express V2M Motherboard Support
*/
# include <linux/device.h>
# include <linux/amba/bus.h>
# include <linux/amba/mmci.h>
# include <linux/io.h>
2011-09-08 13:15:22 +01:00
# include <linux/smp.h>
2010-02-11 21:44:53 +00:00
# include <linux/init.h>
2012-02-23 13:04:51 +00:00
# include <linux/of_address.h>
# include <linux/of_fdt.h>
# include <linux/of_irq.h>
# include <linux/of_platform.h>
2010-02-11 21:44:53 +00:00
# include <linux/platform_device.h>
2011-01-21 15:51:06 +01:00
# include <linux/ata_platform.h>
2010-02-11 21:44:53 +00:00
# include <linux/smsc911x.h>
# include <linux/spinlock.h>
# include <linux/usb/isp1760.h>
2011-05-18 10:51:51 +01:00
# include <linux/mtd/physmap.h>
2012-07-09 11:33:47 +01:00
# include <linux/regulator/fixed.h>
# include <linux/regulator/machine.h>
2012-10-09 12:56:36 +01:00
# include <linux/vexpress.h>
2010-02-11 21:44:53 +00:00
2012-03-28 17:13:53 +01:00
# include <asm/arch_timer.h>
2011-02-28 17:01:04 +01:00
# include <asm/mach-types.h>
2010-02-11 21:44:53 +00:00
# include <asm/sizes.h>
2012-03-28 17:13:53 +01:00
# include <asm/smp_twd.h>
2011-02-28 17:01:04 +01:00
# include <asm/mach/arch.h>
2010-02-11 21:44:53 +00:00
# include <asm/mach/map.h>
# include <asm/mach/time.h>
# include <asm/hardware/arm_timer.h>
2012-02-23 13:04:51 +00:00
# include <asm/hardware/cache-l2x0.h>
# include <asm/hardware/gic.h>
2011-01-05 18:09:03 +00:00
# include <asm/hardware/timer-sp.h>
2010-02-11 21:44:53 +00:00
2011-02-28 17:01:04 +01:00
# include <mach/ct-ca9x4.h>
2010-02-11 21:44:53 +00:00
# include <mach/motherboard.h>
2010-12-15 21:58:50 +00:00
# include <plat/sched_clock.h>
2011-09-08 13:15:22 +01:00
# include <plat/platsmp.h>
2010-02-11 21:44:53 +00:00
# include "core.h"
# define V2M_PA_CS0 0x40000000
# define V2M_PA_CS1 0x44000000
# define V2M_PA_CS2 0x48000000
# define V2M_PA_CS3 0x4c000000
# define V2M_PA_CS7 0x10000000
static struct map_desc v2m_io_desc [ ] __initdata = {
{
2012-01-25 15:37:29 +00:00
. virtual = V2M_PERIPH ,
2010-02-11 21:44:53 +00:00
. pfn = __phys_to_pfn ( V2M_PA_CS7 ) ,
. length = SZ_128K ,
. type = MT_DEVICE ,
} ,
} ;
2012-01-25 15:37:29 +00:00
static void __init v2m_sp804_init ( void __iomem * base , unsigned int irq )
{
if ( WARN_ON ( ! base | | irq = = NO_IRQ ) )
return ;
writel ( 0 , base + TIMER_1_BASE + TIMER_CTRL ) ;
writel ( 0 , base + TIMER_2_BASE + TIMER_CTRL ) ;
2011-01-25 15:53:03 +01:00
2012-01-25 15:37:29 +00:00
sp804_clocksource_init ( base + TIMER_2_BASE , " v2m-timer1 " ) ;
sp804_clockevents_init ( base + TIMER_1_BASE , irq , " v2m-timer0 " ) ;
}
2010-02-11 21:44:53 +00:00
static struct resource v2m_pcie_i2c_resource = {
. start = V2M_SERIAL_BUS_PCI ,
. end = V2M_SERIAL_BUS_PCI + SZ_4K - 1 ,
. flags = IORESOURCE_MEM ,
} ;
static struct platform_device v2m_pcie_i2c_device = {
. name = " versatile-i2c " ,
. id = 0 ,
. num_resources = 1 ,
. resource = & v2m_pcie_i2c_resource ,
} ;
static struct resource v2m_ddc_i2c_resource = {
. start = V2M_SERIAL_BUS_DVI ,
. end = V2M_SERIAL_BUS_DVI + SZ_4K - 1 ,
. flags = IORESOURCE_MEM ,
} ;
static struct platform_device v2m_ddc_i2c_device = {
. name = " versatile-i2c " ,
. id = 1 ,
. num_resources = 1 ,
. resource = & v2m_ddc_i2c_resource ,
} ;
static struct resource v2m_eth_resources [ ] = {
{
. start = V2M_LAN9118 ,
. end = V2M_LAN9118 + SZ_64K - 1 ,
. flags = IORESOURCE_MEM ,
} , {
. start = IRQ_V2M_LAN9118 ,
. end = IRQ_V2M_LAN9118 ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct smsc911x_platform_config v2m_eth_config = {
. flags = SMSC911X_USE_32BIT ,
. irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH ,
. irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL ,
. phy_interface = PHY_INTERFACE_MODE_MII ,
} ;
static struct platform_device v2m_eth_device = {
. name = " smsc911x " ,
. id = - 1 ,
. resource = v2m_eth_resources ,
. num_resources = ARRAY_SIZE ( v2m_eth_resources ) ,
. dev . platform_data = & v2m_eth_config ,
} ;
2012-07-09 11:33:47 +01:00
static struct regulator_consumer_supply v2m_eth_supplies [ ] = {
REGULATOR_SUPPLY ( " vddvario " , " smsc911x " ) ,
REGULATOR_SUPPLY ( " vdd33a " , " smsc911x " ) ,
} ;
2010-02-11 21:44:53 +00:00
static struct resource v2m_usb_resources [ ] = {
{
. start = V2M_ISP1761 ,
. end = V2M_ISP1761 + SZ_128K - 1 ,
. flags = IORESOURCE_MEM ,
} , {
. start = IRQ_V2M_ISP1761 ,
. end = IRQ_V2M_ISP1761 ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct isp1760_platform_data v2m_usb_config = {
. is_isp1761 = true ,
. bus_width_16 = false ,
. port1_otg = true ,
. analog_oc = false ,
. dack_polarity_high = false ,
. dreq_polarity_high = false ,
} ;
static struct platform_device v2m_usb_device = {
. name = " isp1760 " ,
. id = - 1 ,
. resource = v2m_usb_resources ,
. num_resources = ARRAY_SIZE ( v2m_usb_resources ) ,
. dev . platform_data = & v2m_usb_config ,
} ;
2011-05-18 10:51:51 +01:00
static struct physmap_flash_data v2m_flash_data = {
2010-02-11 21:44:53 +00:00
. width = 4 ,
} ;
static struct resource v2m_flash_resources [ ] = {
{
. start = V2M_NOR0 ,
. end = V2M_NOR0 + SZ_64M - 1 ,
. flags = IORESOURCE_MEM ,
} , {
. start = V2M_NOR1 ,
. end = V2M_NOR1 + SZ_64M - 1 ,
. flags = IORESOURCE_MEM ,
} ,
} ;
static struct platform_device v2m_flash_device = {
2011-05-18 10:51:51 +01:00
. name = " physmap-flash " ,
2010-02-11 21:44:53 +00:00
. id = - 1 ,
. resource = v2m_flash_resources ,
. num_resources = ARRAY_SIZE ( v2m_flash_resources ) ,
. dev . platform_data = & v2m_flash_data ,
} ;
2011-01-21 15:51:06 +01:00
static struct pata_platform_info v2m_pata_data = {
. ioport_shift = 2 ,
} ;
static struct resource v2m_pata_resources [ ] = {
{
. start = V2M_CF ,
. end = V2M_CF + 0xff ,
. flags = IORESOURCE_MEM ,
} , {
. start = V2M_CF + 0x100 ,
. end = V2M_CF + SZ_4K - 1 ,
. flags = IORESOURCE_MEM ,
} ,
} ;
static struct platform_device v2m_cf_device = {
. name = " pata_platform " ,
. id = - 1 ,
. resource = v2m_pata_resources ,
. num_resources = ARRAY_SIZE ( v2m_pata_resources ) ,
. dev . platform_data = & v2m_pata_data ,
} ;
2010-02-11 21:44:53 +00:00
static struct mmci_platform_data v2m_mmci_data = {
. ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34 ,
2012-10-09 12:56:36 +01:00
. gpio_wp = VEXPRESS_GPIO_MMC_WPROT ,
. gpio_cd = VEXPRESS_GPIO_MMC_CARDIN ,
} ;
static struct resource v2m_sysreg_resources [ ] = {
{
. start = V2M_SYSREGS ,
. end = V2M_SYSREGS + 0xfff ,
. flags = IORESOURCE_MEM ,
} ,
} ;
static struct platform_device v2m_sysreg_device = {
. name = " vexpress-sysreg " ,
. id = - 1 ,
. resource = v2m_sysreg_resources ,
. num_resources = ARRAY_SIZE ( v2m_sysreg_resources ) ,
} ;
static struct platform_device v2m_muxfpga_device = {
. name = " vexpress-muxfpga " ,
. id = 0 ,
. num_resources = 1 ,
. resource = ( struct resource [ ] ) {
VEXPRESS_RES_FUNC ( 0 , 7 ) ,
}
} ;
static struct platform_device v2m_shutdown_device = {
. name = " vexpress-shutdown " ,
. id = 0 ,
. num_resources = 1 ,
. resource = ( struct resource [ ] ) {
VEXPRESS_RES_FUNC ( 0 , 8 ) ,
}
} ;
static struct platform_device v2m_reboot_device = {
. name = " vexpress-reboot " ,
. id = 0 ,
. num_resources = 1 ,
. resource = ( struct resource [ ] ) {
VEXPRESS_RES_FUNC ( 0 , 9 ) ,
}
} ;
static struct platform_device v2m_dvimode_device = {
. name = " vexpress-dvimode " ,
. id = 0 ,
. num_resources = 1 ,
. resource = ( struct resource [ ] ) {
VEXPRESS_RES_FUNC ( 0 , 11 ) ,
}
2010-02-11 21:44:53 +00:00
} ;
2011-12-18 12:07:09 +00:00
static AMBA_APB_DEVICE ( aaci , " mb:aaci " , 0 , V2M_AACI , IRQ_V2M_AACI , NULL ) ;
static AMBA_APB_DEVICE ( mmci , " mb:mmci " , 0 , V2M_MMCI , IRQ_V2M_MMCI , & v2m_mmci_data ) ;
static AMBA_APB_DEVICE ( kmi0 , " mb:kmi0 " , 0 , V2M_KMI0 , IRQ_V2M_KMI0 , NULL ) ;
static AMBA_APB_DEVICE ( kmi1 , " mb:kmi1 " , 0 , V2M_KMI1 , IRQ_V2M_KMI1 , NULL ) ;
static AMBA_APB_DEVICE ( uart0 , " mb:uart0 " , 0 , V2M_UART0 , IRQ_V2M_UART0 , NULL ) ;
static AMBA_APB_DEVICE ( uart1 , " mb:uart1 " , 0 , V2M_UART1 , IRQ_V2M_UART1 , NULL ) ;
static AMBA_APB_DEVICE ( uart2 , " mb:uart2 " , 0 , V2M_UART2 , IRQ_V2M_UART2 , NULL ) ;
static AMBA_APB_DEVICE ( uart3 , " mb:uart3 " , 0 , V2M_UART3 , IRQ_V2M_UART3 , NULL ) ;
static AMBA_APB_DEVICE ( wdt , " mb:wdt " , 0 , V2M_WDT , IRQ_V2M_WDT , NULL ) ;
static AMBA_APB_DEVICE ( rtc , " mb:rtc " , 0 , V2M_RTC , IRQ_V2M_RTC , NULL ) ;
2010-02-11 21:44:53 +00:00
static struct amba_device * v2m_amba_devs [ ] __initdata = {
& aaci_device ,
& mmci_device ,
& kmi0_device ,
& kmi1_device ,
& uart0_device ,
& uart1_device ,
& uart2_device ,
& uart3_device ,
& wdt_device ,
& rtc_device ,
} ;
2012-07-13 11:48:16 +01:00
static void __init v2m_timer_init ( void )
{
2012-10-09 12:56:36 +01:00
vexpress_clk_init ( ioremap ( V2M_SYSCTL , SZ_4K ) ) ;
2012-07-13 11:48:16 +01:00
v2m_sp804_init ( ioremap ( V2M_TIMER01 , SZ_4K ) , IRQ_V2M_TIMER0 ) ;
}
static struct sys_timer v2m_timer = {
. init = v2m_timer_init ,
2010-02-11 21:44:53 +00:00
} ;
2011-05-30 19:44:22 +01:00
static void __init v2m_init_early ( void )
{
2012-07-13 11:48:16 +01:00
if ( ct_desc - > init_early )
ct_desc - > init_early ( ) ;
2012-10-09 12:56:36 +01:00
versatile_sched_clock_init ( vexpress_get_24mhz_clock_base ( ) , 24000000 ) ;
2010-02-11 21:44:53 +00:00
}
2011-02-28 17:01:04 +01:00
struct ct_desc * ct_desc ;
static struct ct_desc * ct_descs [ ] __initdata = {
# ifdef CONFIG_ARCH_VEXPRESS_CA9X4
& ct_ca9x4_desc ,
# endif
} ;
static void __init v2m_populate_ct_desc ( void )
{
int i ;
u32 current_tile_id ;
ct_desc = NULL ;
2012-10-09 12:56:36 +01:00
current_tile_id = vexpress_get_procid ( VEXPRESS_SITE_MASTER )
2012-01-25 15:37:29 +00:00
& V2M_CT_ID_MASK ;
2011-02-28 17:01:04 +01:00
for ( i = 0 ; i < ARRAY_SIZE ( ct_descs ) & & ! ct_desc ; + + i )
if ( ct_descs [ i ] - > id = = current_tile_id )
ct_desc = ct_descs [ i ] ;
if ( ! ct_desc )
2012-02-23 13:04:51 +00:00
panic ( " vexpress: this kernel does not support core tile ID 0x%08x when booting via ATAGs. \n "
" You may need a device tree blob or a different kernel to boot on this board. \n " ,
current_tile_id ) ;
2011-02-28 17:01:04 +01:00
}
static void __init v2m_map_io ( void )
{
iotable_init ( v2m_io_desc , ARRAY_SIZE ( v2m_io_desc ) ) ;
2012-10-09 12:56:36 +01:00
vexpress_sysreg_early_init ( ioremap ( V2M_SYSREGS , SZ_4K ) ) ;
2011-02-28 17:01:04 +01:00
v2m_populate_ct_desc ( ) ;
ct_desc - > map_io ( ) ;
}
static void __init v2m_init_irq ( void )
{
ct_desc - > init_irq ( ) ;
}
static void __init v2m_init ( void )
2010-02-11 21:44:53 +00:00
{
int i ;
2012-07-09 11:33:47 +01:00
regulator_register_fixed ( 0 , v2m_eth_supplies ,
ARRAY_SIZE ( v2m_eth_supplies ) ) ;
2012-10-09 12:56:36 +01:00
platform_device_register ( & v2m_muxfpga_device ) ;
platform_device_register ( & v2m_shutdown_device ) ;
platform_device_register ( & v2m_reboot_device ) ;
platform_device_register ( & v2m_dvimode_device ) ;
platform_device_register ( & v2m_sysreg_device ) ;
2010-02-11 21:44:53 +00:00
platform_device_register ( & v2m_pcie_i2c_device ) ;
platform_device_register ( & v2m_ddc_i2c_device ) ;
platform_device_register ( & v2m_flash_device ) ;
2011-01-21 15:51:06 +01:00
platform_device_register ( & v2m_cf_device ) ;
2010-02-11 21:44:53 +00:00
platform_device_register ( & v2m_eth_device ) ;
platform_device_register ( & v2m_usb_device ) ;
for ( i = 0 ; i < ARRAY_SIZE ( v2m_amba_devs ) ; i + + )
amba_device_register ( v2m_amba_devs [ i ] , & iomem_resource ) ;
2012-10-09 12:56:36 +01:00
pm_power_off = vexpress_power_off ;
2010-02-11 21:44:53 +00:00
2011-02-28 17:01:04 +01:00
ct_desc - > init_tile ( ) ;
2010-02-11 21:44:53 +00:00
}
2011-02-28 17:01:04 +01:00
MACHINE_START ( VEXPRESS , " ARM-Versatile Express " )
2011-07-05 22:38:18 -04:00
. atag_offset = 0x100 ,
2011-09-08 13:15:22 +01:00
. smp = smp_ops ( vexpress_smp_ops ) ,
2011-02-28 17:01:04 +01:00
. map_io = v2m_map_io ,
. init_early = v2m_init_early ,
. init_irq = v2m_init_irq ,
. timer = & v2m_timer ,
2011-09-06 10:23:45 +01:00
. handle_irq = gic_handle_irq ,
2011-02-28 17:01:04 +01:00
. init_machine = v2m_init ,
2012-10-09 12:56:36 +01:00
. restart = vexpress_restart ,
2011-02-28 17:01:04 +01:00
MACHINE_END
2012-02-23 13:04:51 +00:00
2011-12-09 18:47:39 +00:00
static struct map_desc v2m_rs1_io_desc __initdata = {
. virtual = V2M_PERIPH ,
. pfn = __phys_to_pfn ( 0x1c000000 ) ,
. length = SZ_2M ,
. type = MT_DEVICE ,
} ;
static int __init v2m_dt_scan_memory_map ( unsigned long node , const char * uname ,
int depth , void * data )
{
const char * * map = data ;
if ( strcmp ( uname , " motherboard " ) ! = 0 )
return 0 ;
* map = of_get_flat_dt_prop ( node , " arm,v2m-memory-map " , NULL ) ;
return 1 ;
}
2012-02-23 13:04:51 +00:00
void __init v2m_dt_map_io ( void )
{
2011-12-09 18:47:39 +00:00
const char * map = NULL ;
of_scan_flat_dt ( v2m_dt_scan_memory_map , & map ) ;
if ( map & & strcmp ( map , " rs1 " ) = = 0 )
iotable_init ( & v2m_rs1_io_desc , 1 ) ;
else
iotable_init ( v2m_io_desc , ARRAY_SIZE ( v2m_io_desc ) ) ;
2012-02-23 13:04:51 +00:00
# if defined(CONFIG_SMP)
vexpress_dt_smp_map_io ( ) ;
# endif
}
void __init v2m_dt_init_early ( void )
{
u32 dt_hbi ;
2012-10-09 12:56:36 +01:00
vexpress_sysreg_of_early_init ( ) ;
2012-02-23 13:04:51 +00:00
/* Confirm board type against DT property, if available */
2012-11-30 10:01:51 +00:00
if ( of_property_read_u32 ( of_allnodes , " arm,hbi " , & dt_hbi ) = = 0 ) {
2012-10-09 12:56:36 +01:00
u32 hbi = vexpress_get_hbi ( VEXPRESS_SITE_MASTER ) ;
2012-02-23 13:04:51 +00:00
if ( WARN_ON ( dt_hbi ! = hbi ) )
pr_warning ( " vexpress: DT HBI (%x) is not matching "
" hardware (%x)! \n " , dt_hbi , hbi ) ;
}
}
static struct of_device_id vexpress_irq_match [ ] __initdata = {
{ . compatible = " arm,cortex-a9-gic " , . data = gic_of_init , } ,
{ }
} ;
static void __init v2m_dt_init_irq ( void )
{
of_irq_init ( vexpress_irq_match ) ;
}
static void __init v2m_dt_timer_init ( void )
{
2012-10-16 15:27:12 +01:00
struct device_node * node = NULL ;
2012-02-23 13:04:51 +00:00
2012-10-09 12:56:36 +01:00
vexpress_clk_of_init ( ) ;
2012-02-23 13:04:51 +00:00
2012-10-16 15:27:12 +01:00
do {
node = of_find_compatible_node ( node , NULL , " arm,sp804 " ) ;
} while ( node & & vexpress_get_site_by_node ( node ) ! = VEXPRESS_SITE_MB ) ;
if ( node ) {
pr_info ( " Using SP804 '%s' as a clock & events source \n " ,
node - > full_name ) ;
v2m_sp804_init ( of_iomap ( node , 0 ) ,
irq_of_parse_and_map ( node , 0 ) ) ;
}
2012-07-13 11:48:16 +01:00
2012-03-28 17:13:53 +01:00
if ( arch_timer_of_register ( ) ! = 0 )
twd_local_timer_of_register ( ) ;
if ( arch_timer_sched_clock_init ( ) ! = 0 )
2012-10-09 12:56:36 +01:00
versatile_sched_clock_init ( vexpress_get_24mhz_clock_base ( ) ,
24000000 ) ;
2012-02-23 13:04:51 +00:00
}
static struct sys_timer v2m_dt_timer = {
. init = v2m_dt_timer_init ,
} ;
2012-10-09 12:56:36 +01:00
static const struct of_device_id v2m_dt_bus_match [ ] __initconst = {
{ . compatible = " simple-bus " , } ,
{ . compatible = " arm,amba-bus " , } ,
{ . compatible = " arm,vexpress,config-bus " , } ,
2012-02-23 13:04:51 +00:00
{ }
} ;
static void __init v2m_dt_init ( void )
{
l2x0_of_init ( 0x00400000 , 0xfe0fffff ) ;
2012-10-09 12:56:36 +01:00
of_platform_populate ( NULL , v2m_dt_bus_match , NULL , NULL ) ;
pm_power_off = vexpress_power_off ;
2012-02-23 13:04:51 +00:00
}
2012-10-09 12:56:36 +01:00
static const char * const v2m_dt_match [ ] __initconst = {
2012-02-23 13:04:51 +00:00
" arm,vexpress " ,
2012-09-24 16:40:52 +00:00
" xen,xenvm " ,
2012-02-23 13:04:51 +00:00
NULL ,
} ;
DT_MACHINE_START ( VEXPRESS_DT , " ARM-Versatile Express " )
. dt_compat = v2m_dt_match ,
2011-09-08 13:15:22 +01:00
. smp = smp_ops ( vexpress_smp_ops ) ,
2012-02-23 13:04:51 +00:00
. map_io = v2m_dt_map_io ,
. init_early = v2m_dt_init_early ,
. init_irq = v2m_dt_init_irq ,
. timer = & v2m_dt_timer ,
. init_machine = v2m_dt_init ,
. handle_irq = gic_handle_irq ,
2012-10-09 12:56:36 +01:00
. restart = vexpress_restart ,
2012-02-23 13:04:51 +00:00
MACHINE_END