ARM: smp_twd: add runtime registration support
Add support for the new registration interface to smp_twd. Platforms can populate a struct twd_local_timer with MMIO and IRQ resources, and then call twd_local_timer_register() to have the timer registered with the core. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
		
							parent
							
								
									0ef330e10d
								
							
						
					
					
						commit
						81e46f7b6d
					
				| @ -18,10 +18,26 @@ | ||||
| #define TWD_TIMER_CONTROL_PERIODIC	(1 << 1) | ||||
| #define TWD_TIMER_CONTROL_IT_ENABLE	(1 << 2) | ||||
| 
 | ||||
| #include <linux/ioport.h> | ||||
| 
 | ||||
| struct clock_event_device; | ||||
| 
 | ||||
| extern void __iomem *twd_base; | ||||
| 
 | ||||
| void twd_timer_setup(struct clock_event_device *); | ||||
| int twd_timer_setup(struct clock_event_device *); | ||||
| 
 | ||||
| struct twd_local_timer { | ||||
| 	struct resource	res[2]; | ||||
| }; | ||||
| 
 | ||||
| #define DEFINE_TWD_LOCAL_TIMER(name,base,irq)	\ | ||||
| struct twd_local_timer name __initdata = {	\ | ||||
| 	.res	= {				\ | ||||
| 		DEFINE_RES_MEM(base, 0x10),	\ | ||||
| 		DEFINE_RES_IRQ(irq),		\ | ||||
| 	},					\ | ||||
| }; | ||||
| 
 | ||||
| int twd_local_timer_register(struct twd_local_timer *); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -32,6 +32,7 @@ static struct clk *twd_clk; | ||||
| static unsigned long twd_timer_rate; | ||||
| 
 | ||||
| static struct clock_event_device __percpu **twd_evt; | ||||
| static int twd_ppi; | ||||
| 
 | ||||
| static void twd_set_mode(enum clock_event_mode mode, | ||||
| 			struct clock_event_device *clk) | ||||
| @ -227,7 +228,7 @@ static struct clk *twd_get_clock(void) | ||||
| /*
 | ||||
|  * Setup the local clock events for a CPU. | ||||
|  */ | ||||
| void __cpuinit twd_timer_setup(struct clock_event_device *clk) | ||||
| int __cpuinit twd_timer_setup(struct clock_event_device *clk) | ||||
| { | ||||
| 	struct clock_event_device **this_cpu_clk; | ||||
| 
 | ||||
| @ -237,7 +238,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) | ||||
| 		twd_evt = alloc_percpu(struct clock_event_device *); | ||||
| 		if (!twd_evt) { | ||||
| 			pr_err("twd: can't allocate memory\n"); | ||||
| 			return; | ||||
| 			return -ENOMEM; | ||||
| 		} | ||||
| 
 | ||||
| 		err = request_percpu_irq(clk->irq, twd_handler, | ||||
| @ -245,7 +246,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) | ||||
| 		if (err) { | ||||
| 			pr_err("twd: can't register interrupt %d (%d)\n", | ||||
| 			       clk->irq, err); | ||||
| 			return; | ||||
| 			return err; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @ -265,6 +266,8 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) | ||||
| 	clk->rating = 350; | ||||
| 	clk->set_mode = twd_set_mode; | ||||
| 	clk->set_next_event = twd_set_next_event; | ||||
| 	if (!clk->irq) | ||||
| 		clk->irq = twd_ppi; | ||||
| 
 | ||||
| 	this_cpu_clk = __this_cpu_ptr(twd_evt); | ||||
| 	*this_cpu_clk = clk; | ||||
| @ -272,4 +275,46 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) | ||||
| 	clockevents_config_and_register(clk, twd_timer_rate, | ||||
| 					0xf, 0xffffffff); | ||||
| 	enable_percpu_irq(clk->irq, 0); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static struct local_timer_ops twd_lt_ops __cpuinitdata = { | ||||
| 	.setup	= twd_timer_setup, | ||||
| 	.stop	= twd_timer_stop, | ||||
| }; | ||||
| 
 | ||||
| int __init twd_local_timer_register(struct twd_local_timer *tlt) | ||||
| { | ||||
| 	int err; | ||||
| 
 | ||||
| 	if (twd_base || twd_evt) | ||||
| 		return -EBUSY; | ||||
| 
 | ||||
| 	twd_ppi	= tlt->res[1].start; | ||||
| 
 | ||||
| 	twd_evt = alloc_percpu(struct clock_event_device *); | ||||
| 	twd_base = ioremap(tlt->res[0].start, resource_size(&tlt->res[0])); | ||||
| 	if (!twd_base || !twd_evt) { | ||||
| 		err = -ENOMEM; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	err = request_percpu_irq(twd_ppi, twd_handler, "twd", twd_evt); | ||||
| 	if (err) { | ||||
| 		pr_err("twd: can't register interrupt %d (%d)\n", twd_ppi, err); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	err = local_timer_register(&twd_lt_ops); | ||||
| 	if (err) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
| out: | ||||
| 	iounmap(twd_base); | ||||
| 	free_percpu(twd_evt); | ||||
| 	twd_base = twd_evt = NULL; | ||||
| 	return err; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user