aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 14:22:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 14:22:14 -0400
commit1bf25e78af317e6d5d9b5594dfeb0036e0d589d6 (patch)
tree49dbd2d7bd6856b8ae1864c2dd0c0eb5e36d5398 /arch/arm/common
parent38f56f33ca381751f9b8910f67e7a805ec0b68cb (diff)
parent0592c2189ece16f3e0c5a56245634aba93d0c9dd (diff)
Merge tag 'cleanup-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC late cleanups from Arnd Bergmann: "These are cleanups and smaller changes that either depend on earlier feature branches or came in late during the development cycle. We normally try to get all cleanups early, so these are the exceptions: - A follow-up on the clocksource reworks, hopefully the last time we need to merge clocksource subsystem changes through arm-soc. A first set of patches was part of the original 3.10 arm-soc cleanup series because of interdependencies with timer drivers now moved out of arch/arm. - Migrating the SPEAr13xx platform away from using auxdata for DMA channel descriptions towards using information in device tree, based on the earlier SPEAr multiplatform series - A few follow-ups on the Atmel SAMA5 support and other changes for Atmel at91 based on the larger at91 reworks. - Moving the armada irqchip implementation to drivers/irqchip - Several OMAP cleanups following up on the larger series already merged in 3.10." * tag 'cleanup-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (50 commits) ARM: OMAP4: change the device names in usb_bind_phy ARM: OMAP2+: Fix mismerge for timer.c between ff931c82 and da4a686a ARM: SPEAr: conditionalize SMP code ARM: arch_timer: Silence debug preempt warnings ARM: OMAP: remove unused variable serial: amba-pl011: fix !CONFIG_DMA_ENGINE case ata: arasan: remove the need for platform_data ARM: at91/sama5d34ek.dts: remove not needed compatibility string ARM: at91: dts: add MCI DMA support ARM: at91: dts: add i2c dma support ARM: at91: dts: set #dma-cells to the correct value ARM: at91: suspend both memory controllers on at91sam9263 irqchip: armada-370-xp: slightly cleanup irq controller driver irqchip: armada-370-xp: move IRQ handler to avoid forward declaration irqchip: move IRQ driver for Armada 370/XP ARM: mvebu: move L2 cache initialization in init_early() devtree: add binding documentation for sp804 ARM: integrator-cp: convert use CLKSRC_OF for timer init ARM: versatile: use OF init for sp804 timer ARM: versatile: add versatile dtbs to dtbs target ...
Diffstat (limited to 'arch/arm/common')
-rw-r--r--arch/arm/common/timer-sp.c140
1 files changed, 124 insertions, 16 deletions
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
index 9d2d3ba339ff..ddc740769601 100644
--- a/arch/arm/common/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -25,33 +25,29 @@
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/irq.h> 26#include <linux/irq.h>
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/of.h>
29#include <linux/of_address.h>
30#include <linux/of_irq.h>
28 31
29#include <asm/sched_clock.h> 32#include <asm/sched_clock.h>
30#include <asm/hardware/arm_timer.h> 33#include <asm/hardware/arm_timer.h>
34#include <asm/hardware/timer-sp.h>
31 35
32static long __init sp804_get_clock_rate(const char *name) 36static long __init sp804_get_clock_rate(struct clk *clk)
33{ 37{
34 struct clk *clk;
35 long rate; 38 long rate;
36 int err; 39 int err;
37 40
38 clk = clk_get_sys("sp804", name);
39 if (IS_ERR(clk)) {
40 pr_err("sp804: %s clock not found: %d\n", name,
41 (int)PTR_ERR(clk));
42 return PTR_ERR(clk);
43 }
44
45 err = clk_prepare(clk); 41 err = clk_prepare(clk);
46 if (err) { 42 if (err) {
47 pr_err("sp804: %s clock failed to prepare: %d\n", name, err); 43 pr_err("sp804: clock failed to prepare: %d\n", err);
48 clk_put(clk); 44 clk_put(clk);
49 return err; 45 return err;
50 } 46 }
51 47
52 err = clk_enable(clk); 48 err = clk_enable(clk);
53 if (err) { 49 if (err) {
54 pr_err("sp804: %s clock failed to enable: %d\n", name, err); 50 pr_err("sp804: clock failed to enable: %d\n", err);
55 clk_unprepare(clk); 51 clk_unprepare(clk);
56 clk_put(clk); 52 clk_put(clk);
57 return err; 53 return err;
@@ -59,7 +55,7 @@ static long __init sp804_get_clock_rate(const char *name)
59 55
60 rate = clk_get_rate(clk); 56 rate = clk_get_rate(clk);
61 if (rate < 0) { 57 if (rate < 0) {
62 pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate); 58 pr_err("sp804: clock failed to get rate: %ld\n", rate);
63 clk_disable(clk); 59 clk_disable(clk);
64 clk_unprepare(clk); 60 clk_unprepare(clk);
65 clk_put(clk); 61 clk_put(clk);
@@ -77,9 +73,21 @@ static u32 sp804_read(void)
77 73
78void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, 74void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
79 const char *name, 75 const char *name,
76 struct clk *clk,
80 int use_sched_clock) 77 int use_sched_clock)
81{ 78{
82 long rate = sp804_get_clock_rate(name); 79 long rate;
80
81 if (!clk) {
82 clk = clk_get_sys("sp804", name);
83 if (IS_ERR(clk)) {
84 pr_err("sp804: clock not found: %d\n",
85 (int)PTR_ERR(clk));
86 return;
87 }
88 }
89
90 rate = sp804_get_clock_rate(clk);
83 91
84 if (rate < 0) 92 if (rate < 0)
85 return; 93 return;
@@ -171,12 +179,20 @@ static struct irqaction sp804_timer_irq = {
171 .dev_id = &sp804_clockevent, 179 .dev_id = &sp804_clockevent,
172}; 180};
173 181
174void __init sp804_clockevents_init(void __iomem *base, unsigned int irq, 182void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name)
175 const char *name)
176{ 183{
177 struct clock_event_device *evt = &sp804_clockevent; 184 struct clock_event_device *evt = &sp804_clockevent;
178 long rate = sp804_get_clock_rate(name); 185 long rate;
179 186
187 if (!clk)
188 clk = clk_get_sys("sp804", name);
189 if (IS_ERR(clk)) {
190 pr_err("sp804: %s clock not found: %d\n", name,
191 (int)PTR_ERR(clk));
192 return;
193 }
194
195 rate = sp804_get_clock_rate(clk);
180 if (rate < 0) 196 if (rate < 0)
181 return; 197 return;
182 198
@@ -186,6 +202,98 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
186 evt->irq = irq; 202 evt->irq = irq;
187 evt->cpumask = cpu_possible_mask; 203 evt->cpumask = cpu_possible_mask;
188 204
205 writel(0, base + TIMER_CTRL);
206
189 setup_irq(irq, &sp804_timer_irq); 207 setup_irq(irq, &sp804_timer_irq);
190 clockevents_config_and_register(evt, rate, 0xf, 0xffffffff); 208 clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
191} 209}
210
211static void __init sp804_of_init(struct device_node *np)
212{
213 static bool initialized = false;
214 void __iomem *base;
215 int irq;
216 u32 irq_num = 0;
217 struct clk *clk1, *clk2;
218 const char *name = of_get_property(np, "compatible", NULL);
219
220 base = of_iomap(np, 0);
221 if (WARN_ON(!base))
222 return;
223
224 /* Ensure timers are disabled */
225 writel(0, base + TIMER_CTRL);
226 writel(0, base + TIMER_2_BASE + TIMER_CTRL);
227
228 if (initialized || !of_device_is_available(np))
229 goto err;
230
231 clk1 = of_clk_get(np, 0);
232 if (IS_ERR(clk1))
233 clk1 = NULL;
234
235 /* Get the 2nd clock if the timer has 2 timer clocks */
236 if (of_count_phandle_with_args(np, "clocks", "#clock-cells") == 3) {
237 clk2 = of_clk_get(np, 1);
238 if (IS_ERR(clk2)) {
239 pr_err("sp804: %s clock not found: %d\n", np->name,
240 (int)PTR_ERR(clk2));
241 goto err;
242 }
243 } else
244 clk2 = clk1;
245
246 irq = irq_of_parse_and_map(np, 0);
247 if (irq <= 0)
248 goto err;
249
250 of_property_read_u32(np, "arm,sp804-has-irq", &irq_num);
251 if (irq_num == 2) {
252 __sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name);
253 __sp804_clocksource_and_sched_clock_init(base, name, clk1, 1);
254 } else {
255 __sp804_clockevents_init(base, irq, clk1 , name);
256 __sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE,
257 name, clk2, 1);
258 }
259 initialized = true;
260
261 return;
262err:
263 iounmap(base);
264}
265CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_of_init);
266
267static void __init integrator_cp_of_init(struct device_node *np)
268{
269 static int init_count = 0;
270 void __iomem *base;
271 int irq;
272 const char *name = of_get_property(np, "compatible", NULL);
273
274 base = of_iomap(np, 0);
275 if (WARN_ON(!base))
276 return;
277
278 /* Ensure timer is disabled */
279 writel(0, base + TIMER_CTRL);
280
281 if (init_count == 2 || !of_device_is_available(np))
282 goto err;
283
284 if (!init_count)
285 sp804_clocksource_init(base, name);
286 else {
287 irq = irq_of_parse_and_map(np, 0);
288 if (irq <= 0)
289 goto err;
290
291 sp804_clockevents_init(base, irq, name);
292 }
293
294 init_count++;
295 return;
296err:
297 iounmap(base);
298}
299CLOCKSOURCE_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init);