Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81e46f7b authored by Marc Zyngier's avatar Marc Zyngier
Browse files

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: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 0ef330e1
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -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
+48 −3
Original line number Diff line number Diff line
@@ -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;
}