2010-05-03 07:39:02 +01:00
/*
* Copyright ( C ) ST - Ericsson SA 2010
*
* Author : Rabin Vincent < rabin . vincent @ stericsson . com > for ST - Ericsson
2012-02-06 11:22:24 -08:00
* Author : Lee Jones < lee . jones @ linaro . org > for ST - Ericsson
2010-05-03 07:39:02 +01:00
* License terms : GNU General Public License ( GPL ) version 2
*/
# include <linux/platform_device.h>
# include <linux/io.h>
2011-05-15 22:53:56 +02:00
# include <linux/mfd/db8500-prcmu.h>
2011-05-27 10:30:34 +02:00
# include <linux/clksrc-dbx500-prcmu.h>
2012-02-06 11:22:24 -08:00
# include <linux/sys_soc.h>
# include <linux/err.h>
# include <linux/slab.h>
# include <linux/stat.h>
2012-03-07 17:22:30 +00:00
# include <linux/of.h>
# include <linux/of_irq.h>
2012-10-23 15:55:05 +01:00
# include <linux/irq.h>
2012-08-27 15:45:53 +02:00
# include <linux/platform_data/clk-ux500.h>
2010-05-03 07:39:02 +01:00
# include <asm/hardware/gic.h>
# include <asm/mach/map.h>
# include <mach/hardware.h>
# include <mach/setup.h>
2010-05-03 07:46:56 +01:00
# include <mach/devices.h>
2010-05-03 07:39:02 +01:00
2012-09-25 16:03:45 +01:00
# include "board-mop500.h"
2011-03-29 16:53:29 +02:00
void __iomem * _PRCMU_BASE ;
2012-04-19 21:36:31 +01:00
/*
* FIXME : Should we set up the GPIO domain here ?
*
* The problem is that we cannot put the interrupt resources into the platform
* device until the irqdomain has been added . Right now , we set the GIC interrupt
* domain from init_irq ( ) , then load the gpio driver from
* core_initcall ( nmk_gpio_init ) and add the platform devices from
* arch_initcall ( customize_machine ) .
*
* This feels fragile because it depends on the gpio device getting probed
* _before_ any device uses the gpio interrupts .
*/
2012-03-07 17:22:30 +00:00
static const struct of_device_id ux500_dt_irq_match [ ] = {
{ . compatible = " arm,cortex-a9-gic " , . data = gic_of_init , } ,
{ } ,
} ;
2010-05-03 07:39:02 +01:00
void __init ux500_init_irq ( void )
{
2010-12-08 11:07:57 +05:30
void __iomem * dist_base ;
void __iomem * cpu_base ;
2012-08-22 10:55:03 +02:00
gic_arch_extn . flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND ;
2012-08-09 17:10:36 +02:00
if ( cpu_is_u8500_family ( ) | | cpu_is_ux540_family ( ) ) {
2010-12-08 11:07:57 +05:30
dist_base = __io_address ( U8500_GIC_DIST_BASE ) ;
cpu_base = __io_address ( U8500_GIC_CPU_BASE ) ;
} else
ux500_unknown_soc ( ) ;
2012-03-07 17:22:30 +00:00
# ifdef CONFIG_OF
if ( of_have_populated_dt ( ) )
of_irq_init ( ux500_dt_irq_match ) ;
else
# endif
gic_init ( 0 , 29 , dist_base , cpu_base ) ;
2010-05-26 07:38:54 +01:00
/*
* Init clocks here so that they are available for system timer
* initialization .
*/
2012-01-23 11:54:44 +01:00
if ( cpu_is_u8500_family ( ) )
2011-08-12 10:28:10 +02:00
db8500_prcmu_early_init ( ) ;
2012-08-27 15:45:53 +02:00
if ( cpu_is_u8500_family ( ) )
u8500_clk_init ( ) ;
else if ( cpu_is_u9540 ( ) )
u9540_clk_init ( ) ;
else if ( cpu_is_u8540 ( ) )
u8540_clk_init ( ) ;
2010-05-03 07:39:02 +01:00
}
2012-02-06 11:22:24 -08:00
2012-05-02 17:10:07 +08:00
void __init ux500_init_late ( void )
{
2012-09-25 16:03:45 +01:00
mop500_uib_init ( ) ;
2012-05-02 17:10:07 +08:00
}
2012-02-06 11:22:24 -08:00
static const char * __init ux500_get_machine ( void )
{
return kasprintf ( GFP_KERNEL , " DB%4x " , dbx500_partnumber ( ) ) ;
}
static const char * __init ux500_get_family ( void )
{
return kasprintf ( GFP_KERNEL , " ux500 " ) ;
}
static const char * __init ux500_get_revision ( void )
{
unsigned int rev = dbx500_revision ( ) ;
if ( rev = = 0x01 )
return kasprintf ( GFP_KERNEL , " %s " , " ED " ) ;
else if ( rev > = 0xA0 )
return kasprintf ( GFP_KERNEL , " %d.%d " ,
( rev > > 4 ) - 0xA + 1 , rev & 0xf ) ;
return kasprintf ( GFP_KERNEL , " %s " , " Unknown " ) ;
}
static ssize_t ux500_get_process ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
if ( dbx500_id . process = = 0x00 )
return sprintf ( buf , " Standard \n " ) ;
return sprintf ( buf , " %02xnm \n " , dbx500_id . process ) ;
}
static void __init soc_info_populate ( struct soc_device_attribute * soc_dev_attr ,
const char * soc_id )
{
soc_dev_attr - > soc_id = soc_id ;
soc_dev_attr - > machine = ux500_get_machine ( ) ;
soc_dev_attr - > family = ux500_get_family ( ) ;
soc_dev_attr - > revision = ux500_get_revision ( ) ;
}
struct device_attribute ux500_soc_attr =
__ATTR ( process , S_IRUGO , ux500_get_process , NULL ) ;
struct device * __init ux500_soc_device_init ( const char * soc_id )
{
struct device * parent ;
struct soc_device * soc_dev ;
struct soc_device_attribute * soc_dev_attr ;
soc_dev_attr = kzalloc ( sizeof ( * soc_dev_attr ) , GFP_KERNEL ) ;
if ( ! soc_dev_attr )
return ERR_PTR ( - ENOMEM ) ;
soc_info_populate ( soc_dev_attr , soc_id ) ;
soc_dev = soc_device_register ( soc_dev_attr ) ;
if ( IS_ERR_OR_NULL ( soc_dev ) ) {
kfree ( soc_dev_attr ) ;
return NULL ;
}
parent = soc_device_to_device ( soc_dev ) ;
if ( ! IS_ERR_OR_NULL ( parent ) )
device_create_file ( parent , & ux500_soc_attr ) ;
return parent ;
}