diff options
Diffstat (limited to 'arch/arm/kernel/arch_timer.c')
| -rw-r--r-- | arch/arm/kernel/arch_timer.c | 53 | 
1 files changed, 46 insertions, 7 deletions
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index dd907048f57..1a34eeebc26 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c @@ -17,6 +17,7 @@  #include <linux/jiffies.h>  #include <linux/clockchips.h>  #include <linux/interrupt.h> +#include <linux/of_irq.h>  #include <linux/io.h>  #include <asm/cputype.h> @@ -245,13 +246,10 @@ static struct local_timer_ops arch_timer_ops __cpuinitdata = {  	.stop	= arch_timer_stop,  }; -int __init arch_timer_register(struct arch_timer *at) +static int __init arch_timer_common_register(void)  {  	int err; -	if (at->res[0].start <= 0 || !(at->res[0].flags & IORESOURCE_IRQ)) -		return -EINVAL; -  	err = arch_timer_available();  	if (err)  		return err; @@ -262,7 +260,6 @@ int __init arch_timer_register(struct arch_timer *at)  	clocksource_register_hz(&clocksource_counter, arch_timer_rate); -	arch_timer_ppi = at->res[0].start;  	err = request_percpu_irq(arch_timer_ppi, arch_timer_handler,  				 "arch_timer", arch_timer_evt);  	if (err) { @@ -271,8 +268,7 @@ int __init arch_timer_register(struct arch_timer *at)  		goto out_free;  	} -	if (at->res[1].start > 0 || (at->res[1].flags & IORESOURCE_IRQ)) { -		arch_timer_ppi2 = at->res[1].start; +	if (arch_timer_ppi2) {  		err = request_percpu_irq(arch_timer_ppi2, arch_timer_handler,  					 "arch_timer", arch_timer_evt);  		if (err) { @@ -300,6 +296,49 @@ out_free:  	return err;  } +int __init arch_timer_register(struct arch_timer *at) +{ +	if (at->res[0].start <= 0 || !(at->res[0].flags & IORESOURCE_IRQ)) +		return -EINVAL; + +	arch_timer_ppi = at->res[0].start; + +	if (at->res[1].start > 0 || (at->res[1].flags & IORESOURCE_IRQ)) +		arch_timer_ppi2 = at->res[1].start; + +	return arch_timer_common_register(); +} + +#ifdef CONFIG_OF +static const struct of_device_id arch_timer_of_match[] __initconst = { +	{ .compatible	= "arm,armv7-timer",	}, +	{}, +}; + +int __init arch_timer_of_register(void) +{ +	struct device_node *np; +	u32 freq; + +	np = of_find_matching_node(NULL, arch_timer_of_match); +	if (!np) { +		pr_err("arch_timer: can't find DT node\n"); +		return -ENODEV; +	} + +	/* Try to determine the frequency from the device tree or CNTFRQ */ +	if (!of_property_read_u32(np, "clock-frequency", &freq)) +		arch_timer_rate = freq; + +	arch_timer_ppi = irq_of_parse_and_map(np, 0); +	arch_timer_ppi2 = irq_of_parse_and_map(np, 1); +	pr_info("arch_timer: found %s irqs %d %d\n", +		np->name, arch_timer_ppi, arch_timer_ppi2); + +	return arch_timer_common_register(); +} +#endif +  int __init arch_timer_sched_clock_init(void)  {  	int err;  |