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>
# include <linux/init.h>
# 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/sysdev.h>
# include <linux/usb/isp1760.h>
2010-11-17 10:04:33 +01:00
# include <linux/clkdev.h>
2010-02-11 21:44:53 +00:00
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>
2011-02-28 17:01:04 +01:00
# include <asm/mach/arch.h>
2010-02-11 21:44:53 +00:00
# include <asm/mach/flash.h>
# include <asm/mach/map.h>
# include <asm/mach/time.h>
# include <asm/hardware/arm_timer.h>
2011-01-05 18:09:03 +00:00
# include <asm/hardware/timer-sp.h>
2011-01-25 15:53:03 +01:00
# include <asm/hardware/sp810.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>
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 = {
{
. virtual = __MMIO_P2V ( V2M_PA_CS7 ) ,
. pfn = __phys_to_pfn ( V2M_PA_CS7 ) ,
. length = SZ_128K ,
. type = MT_DEVICE ,
} ,
} ;
2011-02-28 17:01:04 +01:00
static void __init v2m_init_early ( void )
2011-01-11 13:07:52 +00:00
{
2011-02-28 17:01:04 +01:00
ct_desc - > init_early ( ) ;
2011-01-11 13:07:52 +00:00
versatile_sched_clock_init ( MMIO_P2V ( V2M_SYS_24MHZ ) , 24000000 ) ;
}
2010-02-11 21:44:53 +00:00
2010-10-05 11:29:28 +01:00
static void __init v2m_timer_init ( void )
2010-02-11 21:44:53 +00:00
{
2011-01-25 15:53:03 +01:00
u32 scctrl ;
/* Select 1MHz TIMCLK as the reference clock for SP804 timers */
scctrl = readl ( MMIO_P2V ( V2M_SYSCTL + SCCTRL ) ) ;
scctrl | = SCCTRL_TIMEREN0SEL_TIMCLK ;
scctrl | = SCCTRL_TIMEREN1SEL_TIMCLK ;
writel ( scctrl , MMIO_P2V ( V2M_SYSCTL + SCCTRL ) ) ;
2010-02-11 21:44:53 +00:00
writel ( 0 , MMIO_P2V ( V2M_TIMER0 ) + TIMER_CTRL ) ;
writel ( 0 , MMIO_P2V ( V2M_TIMER1 ) + TIMER_CTRL ) ;
sp804_clocksource_init ( MMIO_P2V ( V2M_TIMER1 ) ) ;
sp804_clockevents_init ( MMIO_P2V ( V2M_TIMER0 ) , IRQ_V2M_TIMER0 ) ;
}
2011-02-28 17:01:04 +01:00
static struct sys_timer v2m_timer = {
2010-02-11 21:44:53 +00:00
. init = v2m_timer_init ,
} ;
static DEFINE_SPINLOCK ( v2m_cfg_lock ) ;
int v2m_cfg_write ( u32 devfn , u32 data )
{
/* Configuration interface broken? */
u32 val ;
printk ( " %s: writing %08x to %08x \n " , __func__ , data , devfn ) ;
devfn | = SYS_CFG_START | SYS_CFG_WRITE ;
spin_lock ( & v2m_cfg_lock ) ;
val = readl ( MMIO_P2V ( V2M_SYS_CFGSTAT ) ) ;
writel ( val & ~ SYS_CFG_COMPLETE , MMIO_P2V ( V2M_SYS_CFGSTAT ) ) ;
writel ( data , MMIO_P2V ( V2M_SYS_CFGDATA ) ) ;
writel ( devfn , MMIO_P2V ( V2M_SYS_CFGCTRL ) ) ;
do {
val = readl ( MMIO_P2V ( V2M_SYS_CFGSTAT ) ) ;
} while ( val = = 0 ) ;
spin_unlock ( & v2m_cfg_lock ) ;
return ! ! ( val & SYS_CFG_ERR ) ;
}
int v2m_cfg_read ( u32 devfn , u32 * data )
{
u32 val ;
devfn | = SYS_CFG_START ;
spin_lock ( & v2m_cfg_lock ) ;
writel ( 0 , MMIO_P2V ( V2M_SYS_CFGSTAT ) ) ;
writel ( devfn , MMIO_P2V ( V2M_SYS_CFGCTRL ) ) ;
mb ( ) ;
do {
cpu_relax ( ) ;
val = readl ( MMIO_P2V ( V2M_SYS_CFGSTAT ) ) ;
} while ( val = = 0 ) ;
* data = readl ( MMIO_P2V ( V2M_SYS_CFGDATA ) ) ;
spin_unlock ( & v2m_cfg_lock ) ;
return ! ! ( val & SYS_CFG_ERR ) ;
}
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 ,
} ;
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 ,
} ;
static int v2m_flash_init ( void )
{
writel ( 0 , MMIO_P2V ( V2M_SYS_FLASH ) ) ;
return 0 ;
}
static void v2m_flash_exit ( void )
{
writel ( 0 , MMIO_P2V ( V2M_SYS_FLASH ) ) ;
}
static void v2m_flash_set_vpp ( int on )
{
writel ( on ! = 0 , MMIO_P2V ( V2M_SYS_FLASH ) ) ;
}
static struct flash_platform_data v2m_flash_data = {
. map_name = " cfi_probe " ,
. width = 4 ,
. init = v2m_flash_init ,
. exit = v2m_flash_exit ,
. set_vpp = v2m_flash_set_vpp ,
} ;
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 = {
. name = " armflash " ,
. 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 unsigned int v2m_mmci_status ( struct device * dev )
{
2010-07-29 15:58:59 +01:00
return readl ( MMIO_P2V ( V2M_SYS_MCI ) ) & ( 1 < < 0 ) ;
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 ,
. status = v2m_mmci_status ,
} ;
static AMBA_DEVICE ( aaci , " mb:aaci " , V2M_AACI , NULL ) ;
static AMBA_DEVICE ( mmci , " mb:mmci " , V2M_MMCI , & v2m_mmci_data ) ;
static AMBA_DEVICE ( kmi0 , " mb:kmi0 " , V2M_KMI0 , NULL ) ;
static AMBA_DEVICE ( kmi1 , " mb:kmi1 " , V2M_KMI1 , NULL ) ;
static AMBA_DEVICE ( uart0 , " mb:uart0 " , V2M_UART0 , NULL ) ;
static AMBA_DEVICE ( uart1 , " mb:uart1 " , V2M_UART1 , NULL ) ;
static AMBA_DEVICE ( uart2 , " mb:uart2 " , V2M_UART2 , NULL ) ;
static AMBA_DEVICE ( uart3 , " mb:uart3 " , V2M_UART3 , NULL ) ;
static AMBA_DEVICE ( wdt , " mb:wdt " , V2M_WDT , NULL ) ;
static AMBA_DEVICE ( rtc , " mb:rtc " , V2M_RTC , NULL ) ;
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 ,
} ;
static long v2m_osc_round ( struct clk * clk , unsigned long rate )
{
return rate ;
}
static int v2m_osc1_set ( struct clk * clk , unsigned long rate )
{
return v2m_cfg_write ( SYS_CFG_OSC | SYS_CFG_SITE_MB | 1 , rate ) ;
}
static const struct clk_ops osc1_clk_ops = {
. round = v2m_osc_round ,
. set = v2m_osc1_set ,
} ;
static struct clk osc1_clk = {
. ops = & osc1_clk_ops ,
. rate = 24000000 ,
} ;
static struct clk osc2_clk = {
. rate = 24000000 ,
} ;
2010-07-15 11:01:17 +01:00
static struct clk dummy_apb_pclk ;
2010-02-11 21:44:53 +00:00
static struct clk_lookup v2m_lookups [ ] = {
2010-07-15 11:01:17 +01:00
{ /* AMBA bus clock */
. con_id = " apb_pclk " ,
. clk = & dummy_apb_pclk ,
} , { /* UART0 */
2010-02-11 21:44:53 +00:00
. dev_id = " mb:uart0 " ,
. clk = & osc2_clk ,
} , { /* UART1 */
. dev_id = " mb:uart1 " ,
. clk = & osc2_clk ,
} , { /* UART2 */
. dev_id = " mb:uart2 " ,
. clk = & osc2_clk ,
} , { /* UART3 */
. dev_id = " mb:uart3 " ,
. clk = & osc2_clk ,
} , { /* KMI0 */
. dev_id = " mb:kmi0 " ,
. clk = & osc2_clk ,
} , { /* KMI1 */
. dev_id = " mb:kmi1 " ,
. clk = & osc2_clk ,
} , { /* MMC0 */
. dev_id = " mb:mmci " ,
. clk = & osc2_clk ,
} , { /* CLCD */
. dev_id = " mb:clcd " ,
. clk = & osc1_clk ,
} ,
} ;
static void v2m_power_off ( void )
{
if ( v2m_cfg_write ( SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB , 0 ) )
printk ( KERN_EMERG " Unable to shutdown \n " ) ;
}
static void v2m_restart ( char str , const char * cmd )
{
if ( v2m_cfg_write ( SYS_CFG_REBOOT | SYS_CFG_SITE_MB , 0 ) )
printk ( KERN_EMERG " Unable to reboot \n " ) ;
}
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 ;
current_tile_id = readl ( MMIO_P2V ( V2M_SYS_PROCID0 ) ) & V2M_CT_ID_MASK ;
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 )
panic ( " vexpress: failed to populate core tile description "
" for tile ID 0x%8x \n " , current_tile_id ) ;
}
static void __init v2m_map_io ( void )
{
iotable_init ( v2m_io_desc , ARRAY_SIZE ( v2m_io_desc ) ) ;
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 ;
clkdev_add_table ( v2m_lookups , ARRAY_SIZE ( v2m_lookups ) ) ;
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 ) ;
pm_power_off = v2m_power_off ;
arm_pm_restart = v2m_restart ;
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 " )
. boot_params = PLAT_PHYS_OFFSET + 0x00000100 ,
. map_io = v2m_map_io ,
. init_early = v2m_init_early ,
. init_irq = v2m_init_irq ,
. timer = & v2m_timer ,
. init_machine = v2m_init ,
MACHINE_END