ARM: smp_twd: add device tree support
Add bindings to support DT discovery of the ARM Timer Watchdog (aka TWD). Only the timer side is converted by this patch. Acked-by: Rob Herring <rob.herring@calxeda.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/localtimer.h>
|
||||
@@ -284,37 +286,86 @@ static struct local_timer_ops twd_lt_ops __cpuinitdata = {
|
||||
.stop = twd_timer_stop,
|
||||
};
|
||||
|
||||
int __init twd_local_timer_register(struct twd_local_timer *tlt)
|
||||
static int __init twd_local_timer_common_register(void)
|
||||
{
|
||||
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) {
|
||||
if (!twd_evt) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
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;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
err = local_timer_register(&twd_lt_ops);
|
||||
if (err)
|
||||
goto out;
|
||||
goto out_irq;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
out_irq:
|
||||
free_percpu_irq(twd_ppi, twd_evt);
|
||||
out_free:
|
||||
iounmap(twd_base);
|
||||
twd_base = NULL;
|
||||
free_percpu(twd_evt);
|
||||
twd_base = twd_evt = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int __init twd_local_timer_register(struct twd_local_timer *tlt)
|
||||
{
|
||||
if (twd_base || twd_evt)
|
||||
return -EBUSY;
|
||||
|
||||
twd_ppi = tlt->res[1].start;
|
||||
|
||||
twd_base = ioremap(tlt->res[0].start, resource_size(&tlt->res[0]));
|
||||
if (!twd_base)
|
||||
return -ENOMEM;
|
||||
|
||||
return twd_local_timer_common_register();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
const static struct of_device_id twd_of_match[] __initconst = {
|
||||
{ .compatible = "arm,cortex-a9-twd-timer", },
|
||||
{ .compatible = "arm,cortex-a5-twd-timer", },
|
||||
{ .compatible = "arm,arm11mp-twd-timer", },
|
||||
{ },
|
||||
};
|
||||
|
||||
void __init twd_local_timer_of_register(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
int err;
|
||||
|
||||
np = of_find_matching_node(NULL, twd_of_match);
|
||||
if (!np) {
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
twd_ppi = irq_of_parse_and_map(np, 0);
|
||||
if (!twd_ppi) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
twd_base = of_iomap(np, 0);
|
||||
if (!twd_base) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = twd_local_timer_common_register();
|
||||
|
||||
out:
|
||||
WARN(err, "twd_local_timer_of_register failed (%d)\n", err);
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user