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>
2013-03-21 12:27:25 +01:00
# include <linux/mfd/dbx500-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-11-05 16:18:28 -06:00
# include <linux/irqchip.h>
2012-12-27 13:10:24 -06:00
# include <linux/irqchip/arm-gic.h>
2012-08-27 15:45:53 +02:00
# include <linux/platform_data/clk-ux500.h>
2013-03-19 15:36:12 +01:00
# include <linux/platform_data/arm-ux500-pm.h>
2010-05-03 07:39:02 +01:00
# include <asm/mach/map.h>
2013-03-21 22:51:12 +01:00
# include "setup.h"
2010-05-03 07:39:02 +01:00
2012-09-25 16:03:45 +01:00
# include "board-mop500.h"
2013-03-19 15:41:55 +01:00
# include "db8500-regs.h"
2012-09-19 19:31:19 +02:00
# include "id.h"
2012-09-25 16:03:45 +01:00
2013-06-14 15:22:40 +02:00
void ux500_restart ( enum reboot_mode mode , const char * cmd )
{
local_irq_disable ( ) ;
local_fiq_disable ( ) ;
prcmu_system_reset ( 0 ) ;
}
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 .
*/
2010-05-03 07:39:02 +01:00
void __init ux500_init_irq ( void )
{
2012-08-22 10:55:03 +02:00
gic_arch_extn . flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND ;
2013-11-06 10:05:45 +00:00
irqchip_init ( ) ;
2010-05-26 07:38:54 +01:00
/*
* Init clocks here so that they are available for system timer
* initialization .
*/
2013-03-21 12:27:25 +01:00
if ( cpu_is_u8500_family ( ) ) {
prcmu_early_init ( U8500_PRCMU_BASE , SZ_8K - 1 ) ;
2013-03-19 15:36:12 +01:00
ux500_pm_init ( U8500_PRCMU_BASE , SZ_8K - 1 ) ;
2013-09-17 10:41:42 +01:00
2013-11-06 10:05:45 +00:00
u8500_of_clk_init ( U8500_CLKRST1_BASE ,
U8500_CLKRST2_BASE ,
U8500_CLKRST3_BASE ,
U8500_CLKRST5_BASE ,
U8500_CLKRST6_BASE ) ;
2013-03-21 12:27:25 +01:00
} else if ( cpu_is_u9540 ( ) ) {
prcmu_early_init ( U8500_PRCMU_BASE , SZ_8K - 1 ) ;
2013-03-19 15:36:12 +01:00
ux500_pm_init ( U8500_PRCMU_BASE , SZ_8K - 1 ) ;
2013-05-27 14:41:29 +02:00
u9540_clk_init ( U8500_CLKRST1_BASE , U8500_CLKRST2_BASE ,
2013-03-19 11:21:56 +01:00
U8500_CLKRST3_BASE , U8500_CLKRST5_BASE ,
U8500_CLKRST6_BASE ) ;
2013-03-21 12:27:25 +01:00
} else if ( cpu_is_u8540 ( ) ) {
prcmu_early_init ( U8500_PRCMU_BASE , SZ_8K + SZ_4K - 1 ) ;
2013-03-19 15:36:12 +01:00
ux500_pm_init ( U8500_PRCMU_BASE , SZ_8K + SZ_4K - 1 ) ;
2013-05-27 14:41:29 +02:00
u8540_clk_init ( U8500_CLKRST1_BASE , U8500_CLKRST2_BASE ,
U8500_CLKRST3_BASE , U8500_CLKRST5_BASE ,
U8500_CLKRST6_BASE ) ;
2013-03-21 12:27:25 +01:00
}
2010-05-03 07:39:02 +01: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 ( ) ;
}
2014-04-02 10:01:08 +02:00
static const struct device_attribute ux500_soc_attr =
2012-02-06 11:22:24 -08:00
__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 ) ;
2013-02-24 10:42:27 +00:00
if ( IS_ERR ( soc_dev ) ) {
2012-02-06 11:22:24 -08:00
kfree ( soc_dev_attr ) ;
return NULL ;
}
parent = soc_device_to_device ( soc_dev ) ;
2013-02-24 10:42:27 +00:00
device_create_file ( parent , & ux500_soc_attr ) ;
2012-02-06 11:22:24 -08:00
return parent ;
}