Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 295751
b: refs/heads/master
c: d8e0364
h: refs/heads/master
i:
  295749: 32364ad
  295747: c00eab3
  295743: ca61206
v: v3
  • Loading branch information
Marc Zyngier committed Mar 13, 2012
1 parent ef7b848 commit b4ff3d1
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 81e46f7b6dcec485bcb1f988ba4dc5b20189573c
refs/heads/master: d8e0364364d333feb4564bb7d7d983182b34427e
48 changes: 48 additions & 0 deletions trunk/Documentation/devicetree/bindings/arm/twd.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
* ARM Timer Watchdog

ARM 11MP, Cortex-A5 and Cortex-A9 are often associated with a per-core
Timer-Watchdog (aka TWD), which provides both a per-cpu local timer
and watchdog.

The TWD is usually attached to a GIC to deliver its two per-processor
interrupts.

** Timer node required properties:

- compatible : Should be one of:
"arm,cortex-a9-twd-timer"
"arm,cortex-a5-twd-timer"
"arm,arm11mp-twd-timer"

- interrupts : One interrupt to each core

- reg : Specify the base address and the size of the TWD timer
register window.

Example:

twd-timer@2c000600 {
compatible = "arm,arm11mp-twd-timer"";
reg = <0x2c000600 0x20>;
interrupts = <1 13 0xf01>;
};

** Watchdog node properties:

- compatible : Should be one of:
"arm,cortex-a9-twd-wdt"
"arm,cortex-a5-twd-wdt"
"arm,arm11mp-twd-wdt"

- interrupts : One interrupt to each core

- reg : Specify the base address and the size of the TWD watchdog
register window.

Example:

twd-watchdog@2c000620 {
compatible = "arm,arm11mp-twd-wdt";
reg = <0x2c000620 0x20>;
interrupts = <1 14 0xf01>;
};
8 changes: 8 additions & 0 deletions trunk/arch/arm/include/asm/smp_twd.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,12 @@ struct twd_local_timer name __initdata = { \

int twd_local_timer_register(struct twd_local_timer *);

#ifdef CONFIG_HAVE_ARM_TWD
void twd_local_timer_of_register(void);
#else
static inline void twd_local_timer_of_register(void)
{
}
#endif

#endif
77 changes: 64 additions & 13 deletions trunk/arch/arm/kernel/smp_twd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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

0 comments on commit b4ff3d1

Please sign in to comment.