2011-09-14 11:10:54 +04:00
/*
* Copyright ( C ) ST - Ericsson SA 2011
*
* License Terms : GNU General Public License v2
* Author : Mattias Wallin < mattias . wallin @ stericsson . com > for ST - Ericsson
*/
# include <linux/io.h>
2011-10-03 11:30:20 +04:00
# include <linux/errno.h>
2011-09-14 11:10:54 +04:00
# include <linux/clksrc-dbx500-prcmu.h>
2013-02-07 07:17:47 +04:00
# include <linux/clocksource.h>
2012-03-16 13:53:24 +04:00
# include <linux/of.h>
2012-04-24 13:04:46 +04:00
# include <linux/of_address.h>
2012-10-18 16:01:25 +04:00
# include <linux/platform_data/clocksource-nomadik-mtu.h>
2011-09-14 11:10:54 +04:00
2012-01-10 23:44:19 +04:00
# include <asm/smp_twd.h>
2011-09-14 11:10:54 +04:00
2013-03-22 01:51:12 +04:00
# include "setup.h"
2013-03-22 01:51:08 +04:00
# include "irqs.h"
2011-09-14 11:10:54 +04:00
2013-03-19 18:41:55 +04:00
# include "db8500-regs.h"
2012-09-19 21:31:19 +04:00
# include "id.h"
2012-01-10 23:44:19 +04:00
# ifdef CONFIG_HAVE_ARM_TWD
static DEFINE_TWD_LOCAL_TIMER ( u8500_twd_local_timer ,
U8500_TWD_BASE , IRQ_LOCALTIMER ) ;
static void __init ux500_twd_init ( void )
{
struct twd_local_timer * twd_local_timer ;
int err ;
2012-04-13 15:16:31 +04:00
/* Use this to switch local timer base if changed in new ASICs */
twd_local_timer = & u8500_twd_local_timer ;
2012-01-10 23:44:19 +04:00
2012-03-16 13:53:24 +04:00
if ( of_have_populated_dt ( ) )
2013-02-07 07:17:47 +04:00
clocksource_of_init ( ) ;
2012-03-16 13:53:24 +04:00
else {
err = twd_local_timer_register ( twd_local_timer ) ;
if ( err )
pr_err ( " twd_local_timer_register failed %d \n " , err ) ;
}
2012-01-10 23:44:19 +04:00
}
# else
# define ux500_twd_init() do { } while(0)
# endif
2012-04-24 13:04:46 +04:00
const static struct of_device_id prcmu_timer_of_match [ ] __initconst = {
{ . compatible = " stericsson,db8500-prcmu-timer-4 " , } ,
{ } ,
} ;
2012-11-08 23:40:59 +04:00
void __init ux500_timer_init ( void )
2011-09-14 11:10:54 +04:00
{
2012-01-11 12:46:59 +04:00
void __iomem * mtu_timer_base ;
2011-10-03 11:30:20 +04:00
void __iomem * prcmu_timer_base ;
2012-04-24 13:04:46 +04:00
void __iomem * tmp_base ;
struct device_node * np ;
2011-10-03 11:30:20 +04:00
2012-09-03 17:10:23 +04:00
if ( cpu_is_u8500_family ( ) | | cpu_is_ux540_family ( ) ) {
2012-01-11 12:46:59 +04:00
mtu_timer_base = __io_address ( U8500_MTU0_BASE ) ;
2011-10-03 11:30:20 +04:00
prcmu_timer_base = __io_address ( U8500_PRCMU_TIMER_4_BASE ) ;
2011-09-14 11:10:54 +04:00
} else {
ux500_unknown_soc ( ) ;
}
2012-04-24 13:04:46 +04:00
/* TODO: Once MTU has been DT:ed place code above into else. */
if ( of_have_populated_dt ( ) ) {
2012-06-15 12:27:54 +04:00
# ifdef CONFIG_OF
2012-04-24 13:04:46 +04:00
np = of_find_matching_node ( NULL , prcmu_timer_of_match ) ;
if ( ! np )
2012-06-15 12:27:54 +04:00
# endif
2012-04-24 13:04:46 +04:00
goto dt_fail ;
tmp_base = of_iomap ( np , 0 ) ;
if ( ! tmp_base )
goto dt_fail ;
prcmu_timer_base = tmp_base ;
}
dt_fail :
/* Doing it the old fashioned way. */
2011-09-14 11:10:54 +04:00
/*
* Here we register the timerblocks active in the system .
* Localtimers ( twd ) is started when both cpu is up and running .
* MTU register a clocksource , clockevent and sched_clock .
* Since the MTU is located in the VAPE power domain
* it will be cleared in sleep which makes it unsuitable .
* We however need it as a timer tick ( clockevent )
* during boot to calibrate delay until twd is started .
* RTC - RTT have problems as timer tick during boot since it is
* depending on delay which is not yet calibrated . RTC - RTT is in the
* always - on powerdomain and is used as clockevent instead of twd when
* sleeping .
2012-04-13 15:16:31 +04:00
* The PRCMU timer 4 register a clocksource and
2011-09-14 11:10:54 +04:00
* sched_clock with higher rating then MTU since is always - on .
*
*/
2012-10-18 13:06:02 +04:00
nmdk_timer_init ( mtu_timer_base , IRQ_MTU0 ) ;
2011-10-03 11:30:20 +04:00
clksrc_dbx500_prcmu_init ( prcmu_timer_base ) ;
2012-01-10 23:44:19 +04:00
ux500_twd_init ( ) ;
2011-09-14 11:10:54 +04:00
}