2010-02-05 11:14:49 +00:00
/*
* SH - Mobile Timer
*
* Copyright ( C ) 2010 Magnus Damm
* Copyright ( C ) 2002 - 2009 Paul Mundt
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; version 2 of the License .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
# include <linux/platform_device.h>
2013-04-10 18:27:51 -05:00
# include <linux/clocksource.h>
2012-03-28 19:22:30 +09:00
# include <linux/delay.h>
2014-03-06 12:28:24 +09:00
# include <linux/of_address.h>
2010-02-05 11:14:49 +00:00
2014-08-20 22:03:12 +09:00
static void __init shmobile_setup_delay_hz ( unsigned int max_cpu_core_hz ,
unsigned int mult , unsigned int div )
2014-05-13 15:59:18 +09:00
{
/* calculate a worst-case loops-per-jiffy value
* based on maximum cpu core hz setting and the
* __delay ( ) implementation in arch / arm / lib / delay . S
*
* this will result in a longer delay than expected
* when the cpu core runs on lower frequencies .
*/
unsigned int value = HZ * div / mult ;
if ( ! preset_lpj )
preset_lpj = max_cpu_core_hz / value ;
}
2014-03-06 12:28:24 +09:00
void __init shmobile_init_delay ( void )
{
2014-05-21 15:31:05 +02:00
struct device_node * np , * cpus ;
2014-09-04 16:02:27 +02:00
bool is_a7_a8_a9 = false ;
2014-05-21 15:31:05 +02:00
bool is_a15 = false ;
2014-10-06 08:59:20 +09:00
bool has_arch_timer = false ;
2014-05-21 15:31:05 +02:00
u32 max_freq = 0 ;
cpus = of_find_node_by_path ( " /cpus " ) ;
if ( ! cpus )
return ;
for_each_child_of_node ( cpus , np ) {
u32 freq ;
if ( ! of_property_read_u32 ( np , " clock-frequency " , & freq ) )
max_freq = max ( max_freq , freq ) ;
2014-03-06 12:28:24 +09:00
2014-10-06 08:59:20 +09:00
if ( of_device_is_compatible ( np , " arm,cortex-a8 " ) | |
of_device_is_compatible ( np , " arm,cortex-a9 " ) ) {
2014-09-04 16:02:27 +02:00
is_a7_a8_a9 = true ;
2014-10-06 08:59:20 +09:00
} else if ( of_device_is_compatible ( np , " arm,cortex-a7 " ) ) {
is_a7_a8_a9 = true ;
has_arch_timer = true ;
} else if ( of_device_is_compatible ( np , " arm,cortex-a15 " ) ) {
2014-05-21 15:31:05 +02:00
is_a15 = true ;
2014-10-06 08:59:20 +09:00
has_arch_timer = true ;
}
2014-03-06 12:28:24 +09:00
}
2014-05-21 15:31:05 +02:00
of_node_put ( cpus ) ;
if ( ! max_freq )
return ;
2015-01-28 21:46:45 +09:00
# ifdef CONFIG_ARCH_SHMOBILE_LEGACY
/* Non-multiplatform r8a73a4 SoC cannot use arch timer due
* to GIC being initialized from C and arch timer via DT */
if ( of_machine_is_compatible ( " renesas,r8a73a4 " ) )
has_arch_timer = false ;
2015-01-29 16:25:32 +09:00
/* Non-multiplatform r8a7790 SoC cannot use arch timer due
* to GIC being initialized from C and arch timer via DT */
if ( of_machine_is_compatible ( " renesas,r8a7790 " ) )
has_arch_timer = false ;
2015-01-28 21:46:45 +09:00
# endif
2014-10-06 08:59:20 +09:00
if ( ! has_arch_timer | | ! IS_ENABLED ( CONFIG_ARM_ARCH_TIMER ) ) {
if ( is_a7_a8_a9 )
shmobile_setup_delay_hz ( max_freq , 1 , 3 ) ;
else if ( is_a15 )
shmobile_setup_delay_hz ( max_freq , 2 , 4 ) ;
}
2014-03-06 12:28:24 +09:00
}
2010-02-05 11:14:49 +00:00
static void __init shmobile_late_time_init ( void )
{
/*
* Make sure all compiled - in early timers register themselves .
*
* Run probe ( ) for two " earlytimer " devices , these will be the
* clockevents and clocksource devices respectively . In the event
* that only a clockevents device is available , we - ENODEV on the
* clocksource and the jiffies clocksource is used transparently
* instead . No error handling is necessary here .
*/
early_platform_driver_register_all ( " earlytimer " ) ;
early_platform_driver_probe ( " earlytimer " , 2 , 0 ) ;
}
2012-03-06 17:36:14 +09:00
void __init shmobile_earlytimer_init ( void )
2010-02-05 11:14:49 +00:00
{
late_time_init = shmobile_late_time_init ;
}