diff options
Diffstat (limited to 'arch/arm/mach-shmobile/timer.c')
| -rw-r--r-- | arch/arm/mach-shmobile/timer.c | 45 | 
1 files changed, 45 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c index 62d7052d6f2..68bc0b82226 100644 --- a/arch/arm/mach-shmobile/timer.c +++ b/arch/arm/mach-shmobile/timer.c @@ -21,6 +21,24 @@  #include <linux/platform_device.h>  #include <linux/clocksource.h>  #include <linux/delay.h> +#include <linux/of_address.h> + +void __init shmobile_setup_delay_hz(unsigned int max_cpu_core_hz, +				    unsigned int mult, unsigned int div) +{ +	/* 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; +}  void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,  				 unsigned int mult, unsigned int div) @@ -39,6 +57,33 @@ void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,  		preset_lpj = max_cpu_core_mhz * value;  } +void __init shmobile_init_delay(void) +{ +	struct device_node *np, *parent; +	u32 max_freq, freq; + +	max_freq = 0; + +	parent = of_find_node_by_path("/cpus"); +	if (parent) { +		for_each_child_of_node(parent, np) { +			if (!of_property_read_u32(np, "clock-frequency", &freq)) +				max_freq = max(max_freq, freq); +		} +		of_node_put(parent); +	} + +	if (max_freq) { +		if (of_find_compatible_node(NULL, NULL, "arm,cortex-a8")) +			shmobile_setup_delay_hz(max_freq, 1, 3); +		else if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9")) +			shmobile_setup_delay_hz(max_freq, 1, 3); +		else if (of_find_compatible_node(NULL, NULL, "arm,cortex-a15")) +			if (!IS_ENABLED(CONFIG_ARM_ARCH_TIMER)) +				shmobile_setup_delay_hz(max_freq, 2, 4); +	} +} +  static void __init shmobile_late_time_init(void)  {  	/*  | 
