2005-04-16 15:20:36 -07:00
/*
* linux / arch / arm / mach - integrator / core . c
*
* Copyright ( C ) 2000 - 2003 Deep Blue Solutions Ltd
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 , as
* published by the Free Software Foundation .
*/
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/device.h>
2012-08-04 10:31:24 +00:00
# include <linux/export.h>
2005-04-16 15:20:36 -07:00
# include <linux/spinlock.h>
# include <linux/interrupt.h>
2006-07-01 22:32:32 +01:00
# include <linux/irq.h>
2010-05-22 19:47:18 +01:00
# include <linux/memblock.h>
2005-04-16 15:20:36 -07:00
# include <linux/sched.h>
2005-06-18 10:15:46 +01:00
# include <linux/smp.h>
2006-01-07 13:52:45 +00:00
# include <linux/amba/bus.h>
2006-03-26 23:13:39 +01:00
# include <linux/amba/serial.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2012-11-02 01:31:10 +01:00
# include <linux/stat.h>
2005-04-16 15:20:36 -07:00
2008-08-05 16:14:15 +01:00
# include <mach/hardware.h>
2010-01-14 19:59:37 +00:00
# include <mach/platform.h>
2008-08-05 16:14:15 +01:00
# include <mach/cm.h>
2012-02-26 10:46:48 +01:00
# include <mach/irqs.h>
2011-12-20 11:55:19 +01:00
# include <asm/mach-types.h>
2005-04-16 15:20:36 -07:00
# include <asm/mach/time.h>
2010-05-22 18:18:57 +01:00
# include <asm/pgtable.h>
2005-04-16 15:20:36 -07:00
2012-09-06 09:08:47 +01:00
# include "common.h"
# ifdef CONFIG_ATAGS
2006-03-26 23:13:39 +01:00
2011-12-18 14:50:51 +00:00
# define INTEGRATOR_RTC_IRQ { IRQ_RTCINT }
# define INTEGRATOR_UART0_IRQ { IRQ_UARTINT0 }
# define INTEGRATOR_UART1_IRQ { IRQ_UARTINT1 }
# define KMI0_IRQ { IRQ_KMIINT0 }
# define KMI1_IRQ { IRQ_KMIINT1 }
2005-04-16 15:20:36 -07:00
2012-06-11 00:14:15 +02:00
static AMBA_APB_DEVICE ( rtc , " rtc " , 0 ,
2011-12-18 14:50:51 +00:00
INTEGRATOR_RTC_BASE , INTEGRATOR_RTC_IRQ , NULL ) ;
2005-04-16 15:20:36 -07:00
2012-06-11 00:14:15 +02:00
static AMBA_APB_DEVICE ( uart0 , " uart0 " , 0 ,
2012-11-17 19:24:23 +01:00
INTEGRATOR_UART0_BASE , INTEGRATOR_UART0_IRQ , NULL ) ;
2005-04-16 15:20:36 -07:00
2012-06-11 00:14:15 +02:00
static AMBA_APB_DEVICE ( uart1 , " uart1 " , 0 ,
2012-11-17 19:24:23 +01:00
INTEGRATOR_UART1_BASE , INTEGRATOR_UART1_IRQ , NULL ) ;
2005-04-16 15:20:36 -07:00
2012-06-11 00:14:15 +02:00
static AMBA_APB_DEVICE ( kmi0 , " kmi0 " , 0 , KMI0_BASE , KMI0_IRQ , NULL ) ;
static AMBA_APB_DEVICE ( kmi1 , " kmi1 " , 0 , KMI1_BASE , KMI1_IRQ , NULL ) ;
2005-04-16 15:20:36 -07:00
static struct amba_device * amba_devs [ ] __initdata = {
& rtc_device ,
& uart0_device ,
& uart1_device ,
& kmi0_device ,
& kmi1_device ,
} ;
2012-09-06 09:06:52 +01:00
int __init integrator_init ( bool is_cp )
2005-04-16 15:20:36 -07:00
{
int i ;
2011-12-20 11:55:19 +01:00
/*
* The Integrator / AP lacks necessary AMBA PrimeCell IDs , so we need to
* hard - code them . The Integator / CP and forward have proper cell IDs .
* Else we leave them undefined to the bus driver can autoprobe them .
*/
2013-02-14 13:43:29 +01:00
if ( ! is_cp & & IS_ENABLED ( CONFIG_ARCH_INTEGRATOR_AP ) ) {
2011-12-20 11:55:19 +01:00
rtc_device . periphid = 0x00041030 ;
uart0_device . periphid = 0x00041010 ;
uart1_device . periphid = 0x00041010 ;
kmi0_device . periphid = 0x00041050 ;
kmi1_device . periphid = 0x00041050 ;
2012-11-17 19:24:23 +01:00
uart0_device . dev . platform_data = & ap_uart_data ;
uart1_device . dev . platform_data = & ap_uart_data ;
2011-12-20 11:55:19 +01:00
}
2005-04-16 15:20:36 -07:00
for ( i = 0 ; i < ARRAY_SIZE ( amba_devs ) ; i + + ) {
struct amba_device * d = amba_devs [ i ] ;
amba_device_register ( d , & iomem_resource ) ;
}
return 0 ;
}
2012-09-06 09:08:47 +01:00
# endif
2005-04-16 15:20:36 -07:00
2009-07-03 08:44:46 -05:00
static DEFINE_RAW_SPINLOCK ( cm_lock ) ;
2005-04-16 15:20:36 -07:00
/**
* cm_control - update the CM_CTRL register .
* @ mask : bits to change
* @ set : bits to set
*/
void cm_control ( u32 mask , u32 set )
{
unsigned long flags ;
u32 val ;
2009-07-03 08:44:46 -05:00
raw_spin_lock_irqsave ( & cm_lock , flags ) ;
2005-04-16 15:20:36 -07:00
val = readl ( CM_CTRL ) & ~ mask ;
writel ( val | set , CM_CTRL ) ;
2009-07-03 08:44:46 -05:00
raw_spin_unlock_irqrestore ( & cm_lock , flags ) ;
2005-04-16 15:20:36 -07:00
}
EXPORT_SYMBOL ( cm_control ) ;
2010-05-22 18:18:57 +01:00
/*
* We need to stop things allocating the low memory ; ideally we need a
* better implementation of GFP_DMA which does not assume that DMA - able
* memory starts at zero .
*/
void __init integrator_reserve ( void )
{
2010-05-22 19:47:18 +01:00
memblock_reserve ( PHYS_OFFSET , __pa ( swapper_pg_dir ) - PHYS_OFFSET ) ;
2010-05-22 18:18:57 +01:00
}
2011-11-03 19:54:37 +00:00
/*
* To reset , we hit the on - board reset register in the system FPGA
*/
void integrator_restart ( char mode , const char * cmd )
{
cm_control ( CM_CTRL_RESET , CM_CTRL_RESET ) ;
}
2012-11-02 01:31:10 +01:00
static u32 integrator_id ;
static ssize_t intcp_get_manf ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
return sprintf ( buf , " %02x \n " , integrator_id > > 24 ) ;
}
static struct device_attribute intcp_manf_attr =
__ATTR ( manufacturer , S_IRUGO , intcp_get_manf , NULL ) ;
static ssize_t intcp_get_arch ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
const char * arch ;
switch ( ( integrator_id > > 16 ) & 0xff ) {
case 0x00 :
arch = " ASB little-endian " ;
break ;
case 0x01 :
arch = " AHB little-endian " ;
break ;
case 0x03 :
arch = " AHB-Lite system bus, bi-endian " ;
break ;
case 0x04 :
arch = " AHB " ;
break ;
default :
arch = " Unknown " ;
break ;
}
return sprintf ( buf , " %s \n " , arch ) ;
}
static struct device_attribute intcp_arch_attr =
__ATTR ( architecture , S_IRUGO , intcp_get_arch , NULL ) ;
static ssize_t intcp_get_fpga ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
const char * fpga ;
switch ( ( integrator_id > > 12 ) & 0xf ) {
case 0x01 :
fpga = " XC4062 " ;
break ;
case 0x02 :
fpga = " XC4085 " ;
break ;
case 0x04 :
fpga = " EPM7256AE (Altera PLD) " ;
break ;
default :
fpga = " Unknown " ;
break ;
}
return sprintf ( buf , " %s \n " , fpga ) ;
}
static struct device_attribute intcp_fpga_attr =
__ATTR ( fpga , S_IRUGO , intcp_get_fpga , NULL ) ;
static ssize_t intcp_get_build ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
return sprintf ( buf , " %02x \n " , ( integrator_id > > 4 ) & 0xFF ) ;
}
static struct device_attribute intcp_build_attr =
__ATTR ( build , S_IRUGO , intcp_get_build , NULL ) ;
void integrator_init_sysfs ( struct device * parent , u32 id )
{
integrator_id = id ;
device_create_file ( parent , & intcp_manf_attr ) ;
device_create_file ( parent , & intcp_arch_attr ) ;
device_create_file ( parent , & intcp_fpga_attr ) ;
device_create_file ( parent , & intcp_build_attr ) ;
}