diff options
Diffstat (limited to 'arch/arm/mach-vt8500/timer.c')
-rw-r--r-- | arch/arm/mach-vt8500/timer.c | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/arch/arm/mach-vt8500/timer.c b/arch/arm/mach-vt8500/timer.c index d5376c592ab6..050e1833f2d0 100644 --- a/arch/arm/mach-vt8500/timer.c +++ b/arch/arm/mach-vt8500/timer.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-vt8500/timer.c | 2 | * arch/arm/mach-vt8500/timer_dt.c |
3 | * | 3 | * |
4 | * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz> | ||
4 | * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> | 5 | * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> |
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -18,18 +19,25 @@ | |||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 20 | */ |
20 | 21 | ||
22 | /* | ||
23 | * This file is copied and modified from the original timer.c provided by | ||
24 | * Alexey Charkov. Minor changes have been made for Device Tree Support. | ||
25 | */ | ||
26 | |||
21 | #include <linux/io.h> | 27 | #include <linux/io.h> |
22 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
23 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
24 | #include <linux/clocksource.h> | 30 | #include <linux/clocksource.h> |
25 | #include <linux/clockchips.h> | 31 | #include <linux/clockchips.h> |
26 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
27 | |||
28 | #include <asm/mach/time.h> | 33 | #include <asm/mach/time.h> |
29 | 34 | ||
30 | #include "devices.h" | 35 | #include <linux/of.h> |
36 | #include <linux/of_address.h> | ||
37 | #include <linux/of_irq.h> | ||
31 | 38 | ||
32 | #define VT8500_TIMER_OFFSET 0x0100 | 39 | #define VT8500_TIMER_OFFSET 0x0100 |
40 | #define VT8500_TIMER_HZ 3000000 | ||
33 | #define TIMER_MATCH_VAL 0x0000 | 41 | #define TIMER_MATCH_VAL 0x0000 |
34 | #define TIMER_COUNT_VAL 0x0010 | 42 | #define TIMER_COUNT_VAL 0x0010 |
35 | #define TIMER_STATUS_VAL 0x0014 | 43 | #define TIMER_STATUS_VAL 0x0014 |
@@ -39,7 +47,6 @@ | |||
39 | #define TIMER_COUNT_R_ACTIVE (1 << 5) /* not ready for read */ | 47 | #define TIMER_COUNT_R_ACTIVE (1 << 5) /* not ready for read */ |
40 | #define TIMER_COUNT_W_ACTIVE (1 << 4) /* not ready for write */ | 48 | #define TIMER_COUNT_W_ACTIVE (1 << 4) /* not ready for write */ |
41 | #define TIMER_MATCH_W_ACTIVE (1 << 0) /* not ready for write */ | 49 | #define TIMER_MATCH_W_ACTIVE (1 << 0) /* not ready for write */ |
42 | #define VT8500_TIMER_HZ 3000000 | ||
43 | 50 | ||
44 | #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) | 51 | #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) |
45 | 52 | ||
@@ -55,7 +62,7 @@ static cycle_t vt8500_timer_read(struct clocksource *cs) | |||
55 | return readl(regbase + TIMER_COUNT_VAL); | 62 | return readl(regbase + TIMER_COUNT_VAL); |
56 | } | 63 | } |
57 | 64 | ||
58 | struct clocksource clocksource = { | 65 | static struct clocksource clocksource = { |
59 | .name = "vt8500_timer", | 66 | .name = "vt8500_timer", |
60 | .rating = 200, | 67 | .rating = 200, |
61 | .read = vt8500_timer_read, | 68 | .read = vt8500_timer_read, |
@@ -98,7 +105,7 @@ static void vt8500_timer_set_mode(enum clock_event_mode mode, | |||
98 | } | 105 | } |
99 | } | 106 | } |
100 | 107 | ||
101 | struct clock_event_device clockevent = { | 108 | static struct clock_event_device clockevent = { |
102 | .name = "vt8500_timer", | 109 | .name = "vt8500_timer", |
103 | .features = CLOCK_EVT_FEAT_ONESHOT, | 110 | .features = CLOCK_EVT_FEAT_ONESHOT, |
104 | .rating = 200, | 111 | .rating = 200, |
@@ -115,26 +122,51 @@ static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) | |||
115 | return IRQ_HANDLED; | 122 | return IRQ_HANDLED; |
116 | } | 123 | } |
117 | 124 | ||
118 | struct irqaction irq = { | 125 | static struct irqaction irq = { |
119 | .name = "vt8500_timer", | 126 | .name = "vt8500_timer", |
120 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 127 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, |
121 | .handler = vt8500_timer_interrupt, | 128 | .handler = vt8500_timer_interrupt, |
122 | .dev_id = &clockevent, | 129 | .dev_id = &clockevent, |
123 | }; | 130 | }; |
124 | 131 | ||
125 | static void __init vt8500_timer_init(void) | 132 | static struct of_device_id vt8500_timer_ids[] = { |
133 | { .compatible = "via,vt8500-timer" }, | ||
134 | { } | ||
135 | }; | ||
136 | |||
137 | void __init vt8500_timer_init(void) | ||
126 | { | 138 | { |
127 | regbase = ioremap(wmt_pmc_base + VT8500_TIMER_OFFSET, 0x28); | 139 | struct device_node *np; |
128 | if (!regbase) | 140 | int timer_irq; |
129 | printk(KERN_ERR "vt8500_timer_init: failed to map MMIO registers\n"); | 141 | |
142 | np = of_find_matching_node(NULL, vt8500_timer_ids); | ||
143 | if (!np) { | ||
144 | pr_err("%s: Timer description missing from Device Tree\n", | ||
145 | __func__); | ||
146 | return; | ||
147 | } | ||
148 | regbase = of_iomap(np, 0); | ||
149 | if (!regbase) { | ||
150 | pr_err("%s: Missing iobase description in Device Tree\n", | ||
151 | __func__); | ||
152 | of_node_put(np); | ||
153 | return; | ||
154 | } | ||
155 | timer_irq = irq_of_parse_and_map(np, 0); | ||
156 | if (!timer_irq) { | ||
157 | pr_err("%s: Missing irq description in Device Tree\n", | ||
158 | __func__); | ||
159 | of_node_put(np); | ||
160 | return; | ||
161 | } | ||
130 | 162 | ||
131 | writel(1, regbase + TIMER_CTRL_VAL); | 163 | writel(1, regbase + TIMER_CTRL_VAL); |
132 | writel(0xf, regbase + TIMER_STATUS_VAL); | 164 | writel(0xf, regbase + TIMER_STATUS_VAL); |
133 | writel(~0, regbase + TIMER_MATCH_VAL); | 165 | writel(~0, regbase + TIMER_MATCH_VAL); |
134 | 166 | ||
135 | if (clocksource_register_hz(&clocksource, VT8500_TIMER_HZ)) | 167 | if (clocksource_register_hz(&clocksource, VT8500_TIMER_HZ)) |
136 | printk(KERN_ERR "vt8500_timer_init: clocksource_register failed for %s\n", | 168 | pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n", |
137 | clocksource.name); | 169 | __func__, clocksource.name); |
138 | 170 | ||
139 | clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4); | 171 | clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4); |
140 | 172 | ||
@@ -144,12 +176,9 @@ static void __init vt8500_timer_init(void) | |||
144 | clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent); | 176 | clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent); |
145 | clockevent.cpumask = cpumask_of(0); | 177 | clockevent.cpumask = cpumask_of(0); |
146 | 178 | ||
147 | if (setup_irq(wmt_timer_irq, &irq)) | 179 | if (setup_irq(timer_irq, &irq)) |
148 | printk(KERN_ERR "vt8500_timer_init: setup_irq failed for %s\n", | 180 | pr_err("%s: setup_irq failed for %s\n", __func__, |
149 | clockevent.name); | 181 | clockevent.name); |
150 | clockevents_register_device(&clockevent); | 182 | clockevents_register_device(&clockevent); |
151 | } | 183 | } |
152 | 184 | ||
153 | struct sys_timer vt8500_timer = { | ||
154 | .init = vt8500_timer_init | ||
155 | }; | ||