Commit 275786b71d42bb54c03c15197128d7cb05d4dd8b

Authored by Arnd Bergmann
1 parent 67bdb28718

ARM: sirf: use clocksource_of infrastructure

This moves the two sirf clocksource drivers to drivers/clocksource
and integrates them into the framework for locating the clock sources
automatically.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Tested-by: Barry Song <Baohua.Song@csr.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>

Showing 8 changed files with 527 additions and 563 deletions Side-by-side Diff

arch/arm/mach-prima2/Makefile
... ... @@ -6,6 +6,4 @@
6 6 obj-$(CONFIG_SUSPEND) += pm.o sleep.o
7 7 obj-$(CONFIG_SMP) += platsmp.o headsmp.o
8 8 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
9   -obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
10   -obj-$(CONFIG_ARCH_MARCO) += timer-marco.o
arch/arm/mach-prima2/common.c
... ... @@ -6,6 +6,7 @@
6 6 * Licensed under GPLv2 or later.
7 7 */
8 8  
  9 +#include <linux/clocksource.h>
9 10 #include <linux/init.h>
10 11 #include <linux/kernel.h>
11 12 #include <linux/irqchip.h>
... ... @@ -31,6 +32,13 @@
31 32 sirfsoc_pm_init();
32 33 }
33 34  
  35 +static __init void sirfsoc_init_time(void)
  36 +{
  37 + /* initialize clocking early, we want to set the OS timer */
  38 + sirfsoc_of_clk_init();
  39 + clocksource_of_init();
  40 +}
  41 +
34 42 static __init void sirfsoc_map_io(void)
35 43 {
36 44 sirfsoc_map_lluart();
... ... @@ -48,7 +56,7 @@
48 56 .nr_irqs = 128,
49 57 .map_io = sirfsoc_map_io,
50 58 .init_irq = irqchip_init,
51   - .init_time = sirfsoc_prima2_timer_init,
  59 + .init_time = sirfsoc_init_time,
52 60 .init_machine = sirfsoc_mach_init,
53 61 .init_late = sirfsoc_init_late,
54 62 .dt_compat = atlas6_dt_match,
... ... @@ -67,7 +75,7 @@
67 75 .nr_irqs = 128,
68 76 .map_io = sirfsoc_map_io,
69 77 .init_irq = irqchip_init,
70   - .init_time = sirfsoc_prima2_timer_init,
  78 + .init_time = sirfsoc_init_time,
71 79 .dma_zone_size = SZ_256M,
72 80 .init_machine = sirfsoc_mach_init,
73 81 .init_late = sirfsoc_init_late,
... ... @@ -87,7 +95,7 @@
87 95 .smp = smp_ops(sirfsoc_smp_ops),
88 96 .map_io = sirfsoc_map_io,
89 97 .init_irq = irqchip_init,
90   - .init_time = sirfsoc_marco_timer_init,
  98 + .init_time = sirfsoc_init_time,
91 99 .init_machine = sirfsoc_mach_init,
92 100 .init_late = sirfsoc_init_late,
93 101 .dt_compat = marco_dt_match,
arch/arm/mach-prima2/common.h
... ... @@ -13,9 +13,6 @@
13 13 #include <asm/mach/time.h>
14 14 #include <asm/exception.h>
15 15  
16   -extern void sirfsoc_prima2_timer_init(void);
17   -extern void sirfsoc_marco_timer_init(void);
18   -
19 16 extern struct smp_operations sirfsoc_smp_ops;
20 17 extern void sirfsoc_secondary_startup(void);
21 18 extern void sirfsoc_cpu_die(unsigned int cpu);
arch/arm/mach-prima2/timer-marco.c
1   -/*
2   - * System timer for CSR SiRFprimaII
3   - *
4   - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5   - *
6   - * Licensed under GPLv2 or later.
7   - */
8   -
9   -#include <linux/kernel.h>
10   -#include <linux/interrupt.h>
11   -#include <linux/clockchips.h>
12   -#include <linux/clocksource.h>
13   -#include <linux/bitops.h>
14   -#include <linux/irq.h>
15   -#include <linux/clk.h>
16   -#include <linux/slab.h>
17   -#include <linux/of.h>
18   -#include <linux/of_irq.h>
19   -#include <linux/of_address.h>
20   -#include <asm/sched_clock.h>
21   -#include <asm/localtimer.h>
22   -#include <asm/mach/time.h>
23   -
24   -#include "common.h"
25   -
26   -#define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000
27   -#define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004
28   -#define SIRFSOC_TIMER_MATCH_0 0x0018
29   -#define SIRFSOC_TIMER_MATCH_1 0x001c
30   -#define SIRFSOC_TIMER_COUNTER_0 0x0048
31   -#define SIRFSOC_TIMER_COUNTER_1 0x004c
32   -#define SIRFSOC_TIMER_INTR_STATUS 0x0060
33   -#define SIRFSOC_TIMER_WATCHDOG_EN 0x0064
34   -#define SIRFSOC_TIMER_64COUNTER_CTRL 0x0068
35   -#define SIRFSOC_TIMER_64COUNTER_LO 0x006c
36   -#define SIRFSOC_TIMER_64COUNTER_HI 0x0070
37   -#define SIRFSOC_TIMER_64COUNTER_LOAD_LO 0x0074
38   -#define SIRFSOC_TIMER_64COUNTER_LOAD_HI 0x0078
39   -#define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO 0x007c
40   -#define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI 0x0080
41   -
42   -#define SIRFSOC_TIMER_REG_CNT 6
43   -
44   -static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
45   - SIRFSOC_TIMER_WATCHDOG_EN,
46   - SIRFSOC_TIMER_32COUNTER_0_CTRL,
47   - SIRFSOC_TIMER_32COUNTER_1_CTRL,
48   - SIRFSOC_TIMER_64COUNTER_CTRL,
49   - SIRFSOC_TIMER_64COUNTER_RLATCHED_LO,
50   - SIRFSOC_TIMER_64COUNTER_RLATCHED_HI,
51   -};
52   -
53   -static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
54   -
55   -static void __iomem *sirfsoc_timer_base;
56   -static void __init sirfsoc_of_timer_map(void);
57   -
58   -/* disable count and interrupt */
59   -static inline void sirfsoc_timer_count_disable(int idx)
60   -{
61   - writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7,
62   - sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
63   -}
64   -
65   -/* enable count and interrupt */
66   -static inline void sirfsoc_timer_count_enable(int idx)
67   -{
68   - writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x7,
69   - sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
70   -}
71   -
72   -/* timer interrupt handler */
73   -static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
74   -{
75   - struct clock_event_device *ce = dev_id;
76   - int cpu = smp_processor_id();
77   -
78   - /* clear timer interrupt */
79   - writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
80   -
81   - if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
82   - sirfsoc_timer_count_disable(cpu);
83   -
84   - ce->event_handler(ce);
85   -
86   - return IRQ_HANDLED;
87   -}
88   -
89   -/* read 64-bit timer counter */
90   -static cycle_t sirfsoc_timer_read(struct clocksource *cs)
91   -{
92   - u64 cycles;
93   -
94   - writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
95   - BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
96   -
97   - cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI);
98   - cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO);
99   -
100   - return cycles;
101   -}
102   -
103   -static int sirfsoc_timer_set_next_event(unsigned long delta,
104   - struct clock_event_device *ce)
105   -{
106   - int cpu = smp_processor_id();
107   -
108   - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 +
109   - 4 * cpu);
110   - writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 +
111   - 4 * cpu);
112   -
113   - /* enable the tick */
114   - sirfsoc_timer_count_enable(cpu);
115   -
116   - return 0;
117   -}
118   -
119   -static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
120   - struct clock_event_device *ce)
121   -{
122   - switch (mode) {
123   - case CLOCK_EVT_MODE_ONESHOT:
124   - /* enable in set_next_event */
125   - break;
126   - default:
127   - break;
128   - }
129   -
130   - sirfsoc_timer_count_disable(smp_processor_id());
131   -}
132   -
133   -static void sirfsoc_clocksource_suspend(struct clocksource *cs)
134   -{
135   - int i;
136   -
137   - for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
138   - sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
139   -}
140   -
141   -static void sirfsoc_clocksource_resume(struct clocksource *cs)
142   -{
143   - int i;
144   -
145   - for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
146   - writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
147   -
148   - writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2],
149   - sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
150   - writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1],
151   - sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
152   -
153   - writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
154   - BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
155   -}
156   -
157   -static struct clock_event_device sirfsoc_clockevent = {
158   - .name = "sirfsoc_clockevent",
159   - .rating = 200,
160   - .features = CLOCK_EVT_FEAT_ONESHOT,
161   - .set_mode = sirfsoc_timer_set_mode,
162   - .set_next_event = sirfsoc_timer_set_next_event,
163   -};
164   -
165   -static struct clocksource sirfsoc_clocksource = {
166   - .name = "sirfsoc_clocksource",
167   - .rating = 200,
168   - .mask = CLOCKSOURCE_MASK(64),
169   - .flags = CLOCK_SOURCE_IS_CONTINUOUS,
170   - .read = sirfsoc_timer_read,
171   - .suspend = sirfsoc_clocksource_suspend,
172   - .resume = sirfsoc_clocksource_resume,
173   -};
174   -
175   -static struct irqaction sirfsoc_timer_irq = {
176   - .name = "sirfsoc_timer0",
177   - .flags = IRQF_TIMER | IRQF_NOBALANCING,
178   - .handler = sirfsoc_timer_interrupt,
179   - .dev_id = &sirfsoc_clockevent,
180   -};
181   -
182   -#ifdef CONFIG_LOCAL_TIMERS
183   -
184   -static struct irqaction sirfsoc_timer1_irq = {
185   - .name = "sirfsoc_timer1",
186   - .flags = IRQF_TIMER | IRQF_NOBALANCING,
187   - .handler = sirfsoc_timer_interrupt,
188   -};
189   -
190   -static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce)
191   -{
192   - /* Use existing clock_event for cpu 0 */
193   - if (!smp_processor_id())
194   - return 0;
195   -
196   - ce->irq = sirfsoc_timer1_irq.irq;
197   - ce->name = "local_timer";
198   - ce->features = sirfsoc_clockevent.features;
199   - ce->rating = sirfsoc_clockevent.rating;
200   - ce->set_mode = sirfsoc_timer_set_mode;
201   - ce->set_next_event = sirfsoc_timer_set_next_event;
202   - ce->shift = sirfsoc_clockevent.shift;
203   - ce->mult = sirfsoc_clockevent.mult;
204   - ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns;
205   - ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns;
206   -
207   - sirfsoc_timer1_irq.dev_id = ce;
208   - BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq));
209   - irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1));
210   -
211   - clockevents_register_device(ce);
212   - return 0;
213   -}
214   -
215   -static void sirfsoc_local_timer_stop(struct clock_event_device *ce)
216   -{
217   - sirfsoc_timer_count_disable(1);
218   -
219   - remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
220   -}
221   -
222   -static struct local_timer_ops sirfsoc_local_timer_ops __cpuinitdata = {
223   - .setup = sirfsoc_local_timer_setup,
224   - .stop = sirfsoc_local_timer_stop,
225   -};
226   -#endif /* CONFIG_LOCAL_TIMERS */
227   -
228   -static void __init sirfsoc_clockevent_init(void)
229   -{
230   - clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
231   -
232   - sirfsoc_clockevent.max_delta_ns =
233   - clockevent_delta2ns(-2, &sirfsoc_clockevent);
234   - sirfsoc_clockevent.min_delta_ns =
235   - clockevent_delta2ns(2, &sirfsoc_clockevent);
236   -
237   - sirfsoc_clockevent.cpumask = cpumask_of(0);
238   - clockevents_register_device(&sirfsoc_clockevent);
239   -#ifdef CONFIG_LOCAL_TIMERS
240   - local_timer_register(&sirfsoc_local_timer_ops);
241   -#endif
242   -}
243   -
244   -/* initialize the kernel jiffy timer source */
245   -void __init sirfsoc_marco_timer_init(void)
246   -{
247   - unsigned long rate;
248   - u32 timer_div;
249   - struct clk *clk;
250   -
251   - /* initialize clocking early, we want to set the OS timer */
252   - sirfsoc_of_clk_init();
253   -
254   - /* timer's input clock is io clock */
255   - clk = clk_get_sys("io", NULL);
256   -
257   - BUG_ON(IS_ERR(clk));
258   - rate = clk_get_rate(clk);
259   -
260   - BUG_ON(rate < CLOCK_TICK_RATE);
261   - BUG_ON(rate % CLOCK_TICK_RATE);
262   -
263   - sirfsoc_of_timer_map();
264   -
265   - /* Initialize the timer dividers */
266   - timer_div = rate / CLOCK_TICK_RATE - 1;
267   - writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
268   - writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
269   - writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
270   -
271   - /* Initialize timer counters to 0 */
272   - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
273   - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
274   - writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
275   - BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
276   - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0);
277   - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1);
278   -
279   - /* Clear all interrupts */
280   - writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
281   -
282   - BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
283   -
284   - BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
285   -
286   - sirfsoc_clockevent_init();
287   -}
288   -
289   -static struct of_device_id timer_ids[] = {
290   - { .compatible = "sirf,marco-tick" },
291   - {},
292   -};
293   -
294   -static void __init sirfsoc_of_timer_map(void)
295   -{
296   - struct device_node *np;
297   -
298   - np = of_find_matching_node(NULL, timer_ids);
299   - if (!np)
300   - return;
301   - sirfsoc_timer_base = of_iomap(np, 0);
302   - if (!sirfsoc_timer_base)
303   - panic("unable to map timer cpu registers\n");
304   -
305   - sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
306   - if (!sirfsoc_timer_irq.irq)
307   - panic("No irq passed for timer0 via DT\n");
308   -
309   -#ifdef CONFIG_LOCAL_TIMERS
310   - sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1);
311   - if (!sirfsoc_timer1_irq.irq)
312   - panic("No irq passed for timer1 via DT\n");
313   -#endif
314   -
315   - of_node_put(np);
316   -}
arch/arm/mach-prima2/timer-prima2.c
1   -/*
2   - * System timer for CSR SiRFprimaII
3   - *
4   - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5   - *
6   - * Licensed under GPLv2 or later.
7   - */
8   -
9   -#include <linux/kernel.h>
10   -#include <linux/interrupt.h>
11   -#include <linux/clockchips.h>
12   -#include <linux/clocksource.h>
13   -#include <linux/bitops.h>
14   -#include <linux/irq.h>
15   -#include <linux/clk.h>
16   -#include <linux/err.h>
17   -#include <linux/slab.h>
18   -#include <linux/of.h>
19   -#include <linux/of_irq.h>
20   -#include <linux/of_address.h>
21   -#include <mach/map.h>
22   -#include <asm/sched_clock.h>
23   -#include <asm/mach/time.h>
24   -
25   -#include "common.h"
26   -
27   -#define SIRFSOC_TIMER_COUNTER_LO 0x0000
28   -#define SIRFSOC_TIMER_COUNTER_HI 0x0004
29   -#define SIRFSOC_TIMER_MATCH_0 0x0008
30   -#define SIRFSOC_TIMER_MATCH_1 0x000C
31   -#define SIRFSOC_TIMER_MATCH_2 0x0010
32   -#define SIRFSOC_TIMER_MATCH_3 0x0014
33   -#define SIRFSOC_TIMER_MATCH_4 0x0018
34   -#define SIRFSOC_TIMER_MATCH_5 0x001C
35   -#define SIRFSOC_TIMER_STATUS 0x0020
36   -#define SIRFSOC_TIMER_INT_EN 0x0024
37   -#define SIRFSOC_TIMER_WATCHDOG_EN 0x0028
38   -#define SIRFSOC_TIMER_DIV 0x002C
39   -#define SIRFSOC_TIMER_LATCH 0x0030
40   -#define SIRFSOC_TIMER_LATCHED_LO 0x0034
41   -#define SIRFSOC_TIMER_LATCHED_HI 0x0038
42   -
43   -#define SIRFSOC_TIMER_WDT_INDEX 5
44   -
45   -#define SIRFSOC_TIMER_LATCH_BIT BIT(0)
46   -
47   -#define SIRFSOC_TIMER_REG_CNT 11
48   -
49   -static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
50   - SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
51   - SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
52   - SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
53   - SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
54   -};
55   -
56   -static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
57   -
58   -static void __iomem *sirfsoc_timer_base;
59   -static void __init sirfsoc_of_timer_map(void);
60   -
61   -/* timer0 interrupt handler */
62   -static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
63   -{
64   - struct clock_event_device *ce = dev_id;
65   -
66   - WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0)));
67   -
68   - /* clear timer0 interrupt */
69   - writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
70   -
71   - ce->event_handler(ce);
72   -
73   - return IRQ_HANDLED;
74   -}
75   -
76   -/* read 64-bit timer counter */
77   -static cycle_t sirfsoc_timer_read(struct clocksource *cs)
78   -{
79   - u64 cycles;
80   -
81   - /* latch the 64-bit timer counter */
82   - writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
83   - cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI);
84   - cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
85   -
86   - return cycles;
87   -}
88   -
89   -static int sirfsoc_timer_set_next_event(unsigned long delta,
90   - struct clock_event_device *ce)
91   -{
92   - unsigned long now, next;
93   -
94   - writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
95   - now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
96   - next = now + delta;
97   - writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0);
98   - writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
99   - now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
100   -
101   - return next - now > delta ? -ETIME : 0;
102   -}
103   -
104   -static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
105   - struct clock_event_device *ce)
106   -{
107   - u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
108   - switch (mode) {
109   - case CLOCK_EVT_MODE_PERIODIC:
110   - WARN_ON(1);
111   - break;
112   - case CLOCK_EVT_MODE_ONESHOT:
113   - writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
114   - break;
115   - case CLOCK_EVT_MODE_SHUTDOWN:
116   - writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
117   - break;
118   - case CLOCK_EVT_MODE_UNUSED:
119   - case CLOCK_EVT_MODE_RESUME:
120   - break;
121   - }
122   -}
123   -
124   -static void sirfsoc_clocksource_suspend(struct clocksource *cs)
125   -{
126   - int i;
127   -
128   - writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
129   -
130   - for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
131   - sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
132   -}
133   -
134   -static void sirfsoc_clocksource_resume(struct clocksource *cs)
135   -{
136   - int i;
137   -
138   - for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
139   - writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
140   -
141   - writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
142   - writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
143   -}
144   -
145   -static struct clock_event_device sirfsoc_clockevent = {
146   - .name = "sirfsoc_clockevent",
147   - .rating = 200,
148   - .features = CLOCK_EVT_FEAT_ONESHOT,
149   - .set_mode = sirfsoc_timer_set_mode,
150   - .set_next_event = sirfsoc_timer_set_next_event,
151   -};
152   -
153   -static struct clocksource sirfsoc_clocksource = {
154   - .name = "sirfsoc_clocksource",
155   - .rating = 200,
156   - .mask = CLOCKSOURCE_MASK(64),
157   - .flags = CLOCK_SOURCE_IS_CONTINUOUS,
158   - .read = sirfsoc_timer_read,
159   - .suspend = sirfsoc_clocksource_suspend,
160   - .resume = sirfsoc_clocksource_resume,
161   -};
162   -
163   -static struct irqaction sirfsoc_timer_irq = {
164   - .name = "sirfsoc_timer0",
165   - .flags = IRQF_TIMER,
166   - .irq = 0,
167   - .handler = sirfsoc_timer_interrupt,
168   - .dev_id = &sirfsoc_clockevent,
169   -};
170   -
171   -/* Overwrite weak default sched_clock with more precise one */
172   -static u32 notrace sirfsoc_read_sched_clock(void)
173   -{
174   - return (u32)(sirfsoc_timer_read(NULL) & 0xffffffff);
175   -}
176   -
177   -static void __init sirfsoc_clockevent_init(void)
178   -{
179   - sirfsoc_clockevent.cpumask = cpumask_of(0);
180   - clockevents_config_and_register(&sirfsoc_clockevent, CLOCK_TICK_RATE,
181   - 2, -2);
182   -}
183   -
184   -/* initialize the kernel jiffy timer source */
185   -void __init sirfsoc_prima2_timer_init(void)
186   -{
187   - unsigned long rate;
188   - struct clk *clk;
189   -
190   - /* initialize clocking early, we want to set the OS timer */
191   - sirfsoc_of_clk_init();
192   -
193   - /* timer's input clock is io clock */
194   - clk = clk_get_sys("io", NULL);
195   -
196   - BUG_ON(IS_ERR(clk));
197   -
198   - rate = clk_get_rate(clk);
199   -
200   - BUG_ON(rate < CLOCK_TICK_RATE);
201   - BUG_ON(rate % CLOCK_TICK_RATE);
202   -
203   - sirfsoc_of_timer_map();
204   -
205   - writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
206   - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
207   - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
208   - writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
209   -
210   - BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
211   -
212   - setup_sched_clock(sirfsoc_read_sched_clock, 32, CLOCK_TICK_RATE);
213   -
214   - BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
215   -
216   - sirfsoc_clockevent_init();
217   -}
218   -
219   -static struct of_device_id timer_ids[] = {
220   - { .compatible = "sirf,prima2-tick" },
221   - {},
222   -};
223   -
224   -static void __init sirfsoc_of_timer_map(void)
225   -{
226   - struct device_node *np;
227   -
228   - np = of_find_matching_node(NULL, timer_ids);
229   - if (!np)
230   - return;
231   - sirfsoc_timer_base = of_iomap(np, 0);
232   - if (!sirfsoc_timer_base)
233   - panic("unable to map timer cpu registers\n");
234   -
235   - /* Get the interrupts property */
236   - sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
237   -
238   - of_node_put(np);
239   -}
drivers/clocksource/Makefile
... ... @@ -16,6 +16,8 @@
16 16 obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o
17 17 obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o
18 18 obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
  19 +obj-$(CONFIG_ARCH_MARCO) += timer-marco.o
  20 +obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
19 21 obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o
20 22 obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o
21 23 obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
drivers/clocksource/timer-marco.c
  1 +/*
  2 + * System timer for CSR SiRFprimaII
  3 + *
  4 + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
  5 + *
  6 + * Licensed under GPLv2 or later.
  7 + */
  8 +
  9 +#include <linux/kernel.h>
  10 +#include <linux/interrupt.h>
  11 +#include <linux/clockchips.h>
  12 +#include <linux/clocksource.h>
  13 +#include <linux/bitops.h>
  14 +#include <linux/irq.h>
  15 +#include <linux/clk.h>
  16 +#include <linux/slab.h>
  17 +#include <linux/of.h>
  18 +#include <linux/of_irq.h>
  19 +#include <linux/of_address.h>
  20 +#include <asm/sched_clock.h>
  21 +#include <asm/localtimer.h>
  22 +#include <asm/mach/time.h>
  23 +
  24 +#define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000
  25 +#define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004
  26 +#define SIRFSOC_TIMER_MATCH_0 0x0018
  27 +#define SIRFSOC_TIMER_MATCH_1 0x001c
  28 +#define SIRFSOC_TIMER_COUNTER_0 0x0048
  29 +#define SIRFSOC_TIMER_COUNTER_1 0x004c
  30 +#define SIRFSOC_TIMER_INTR_STATUS 0x0060
  31 +#define SIRFSOC_TIMER_WATCHDOG_EN 0x0064
  32 +#define SIRFSOC_TIMER_64COUNTER_CTRL 0x0068
  33 +#define SIRFSOC_TIMER_64COUNTER_LO 0x006c
  34 +#define SIRFSOC_TIMER_64COUNTER_HI 0x0070
  35 +#define SIRFSOC_TIMER_64COUNTER_LOAD_LO 0x0074
  36 +#define SIRFSOC_TIMER_64COUNTER_LOAD_HI 0x0078
  37 +#define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO 0x007c
  38 +#define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI 0x0080
  39 +
  40 +#define SIRFSOC_TIMER_REG_CNT 6
  41 +
  42 +static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
  43 + SIRFSOC_TIMER_WATCHDOG_EN,
  44 + SIRFSOC_TIMER_32COUNTER_0_CTRL,
  45 + SIRFSOC_TIMER_32COUNTER_1_CTRL,
  46 + SIRFSOC_TIMER_64COUNTER_CTRL,
  47 + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO,
  48 + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI,
  49 +};
  50 +
  51 +static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
  52 +
  53 +static void __iomem *sirfsoc_timer_base;
  54 +
  55 +/* disable count and interrupt */
  56 +static inline void sirfsoc_timer_count_disable(int idx)
  57 +{
  58 + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7,
  59 + sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
  60 +}
  61 +
  62 +/* enable count and interrupt */
  63 +static inline void sirfsoc_timer_count_enable(int idx)
  64 +{
  65 + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x7,
  66 + sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
  67 +}
  68 +
  69 +/* timer interrupt handler */
  70 +static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
  71 +{
  72 + struct clock_event_device *ce = dev_id;
  73 + int cpu = smp_processor_id();
  74 +
  75 + /* clear timer interrupt */
  76 + writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
  77 +
  78 + if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
  79 + sirfsoc_timer_count_disable(cpu);
  80 +
  81 + ce->event_handler(ce);
  82 +
  83 + return IRQ_HANDLED;
  84 +}
  85 +
  86 +/* read 64-bit timer counter */
  87 +static cycle_t sirfsoc_timer_read(struct clocksource *cs)
  88 +{
  89 + u64 cycles;
  90 +
  91 + writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
  92 + BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
  93 +
  94 + cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI);
  95 + cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO);
  96 +
  97 + return cycles;
  98 +}
  99 +
  100 +static int sirfsoc_timer_set_next_event(unsigned long delta,
  101 + struct clock_event_device *ce)
  102 +{
  103 + int cpu = smp_processor_id();
  104 +
  105 + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 +
  106 + 4 * cpu);
  107 + writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 +
  108 + 4 * cpu);
  109 +
  110 + /* enable the tick */
  111 + sirfsoc_timer_count_enable(cpu);
  112 +
  113 + return 0;
  114 +}
  115 +
  116 +static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
  117 + struct clock_event_device *ce)
  118 +{
  119 + switch (mode) {
  120 + case CLOCK_EVT_MODE_ONESHOT:
  121 + /* enable in set_next_event */
  122 + break;
  123 + default:
  124 + break;
  125 + }
  126 +
  127 + sirfsoc_timer_count_disable(smp_processor_id());
  128 +}
  129 +
  130 +static void sirfsoc_clocksource_suspend(struct clocksource *cs)
  131 +{
  132 + int i;
  133 +
  134 + for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
  135 + sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
  136 +}
  137 +
  138 +static void sirfsoc_clocksource_resume(struct clocksource *cs)
  139 +{
  140 + int i;
  141 +
  142 + for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
  143 + writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
  144 +
  145 + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2],
  146 + sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
  147 + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1],
  148 + sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
  149 +
  150 + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
  151 + BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
  152 +}
  153 +
  154 +static struct clock_event_device sirfsoc_clockevent = {
  155 + .name = "sirfsoc_clockevent",
  156 + .rating = 200,
  157 + .features = CLOCK_EVT_FEAT_ONESHOT,
  158 + .set_mode = sirfsoc_timer_set_mode,
  159 + .set_next_event = sirfsoc_timer_set_next_event,
  160 +};
  161 +
  162 +static struct clocksource sirfsoc_clocksource = {
  163 + .name = "sirfsoc_clocksource",
  164 + .rating = 200,
  165 + .mask = CLOCKSOURCE_MASK(64),
  166 + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  167 + .read = sirfsoc_timer_read,
  168 + .suspend = sirfsoc_clocksource_suspend,
  169 + .resume = sirfsoc_clocksource_resume,
  170 +};
  171 +
  172 +static struct irqaction sirfsoc_timer_irq = {
  173 + .name = "sirfsoc_timer0",
  174 + .flags = IRQF_TIMER | IRQF_NOBALANCING,
  175 + .handler = sirfsoc_timer_interrupt,
  176 + .dev_id = &sirfsoc_clockevent,
  177 +};
  178 +
  179 +#ifdef CONFIG_LOCAL_TIMERS
  180 +
  181 +static struct irqaction sirfsoc_timer1_irq = {
  182 + .name = "sirfsoc_timer1",
  183 + .flags = IRQF_TIMER | IRQF_NOBALANCING,
  184 + .handler = sirfsoc_timer_interrupt,
  185 +};
  186 +
  187 +static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce)
  188 +{
  189 + /* Use existing clock_event for cpu 0 */
  190 + if (!smp_processor_id())
  191 + return 0;
  192 +
  193 + ce->irq = sirfsoc_timer1_irq.irq;
  194 + ce->name = "local_timer";
  195 + ce->features = sirfsoc_clockevent.features;
  196 + ce->rating = sirfsoc_clockevent.rating;
  197 + ce->set_mode = sirfsoc_timer_set_mode;
  198 + ce->set_next_event = sirfsoc_timer_set_next_event;
  199 + ce->shift = sirfsoc_clockevent.shift;
  200 + ce->mult = sirfsoc_clockevent.mult;
  201 + ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns;
  202 + ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns;
  203 +
  204 + sirfsoc_timer1_irq.dev_id = ce;
  205 + BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq));
  206 + irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1));
  207 +
  208 + clockevents_register_device(ce);
  209 + return 0;
  210 +}
  211 +
  212 +static void sirfsoc_local_timer_stop(struct clock_event_device *ce)
  213 +{
  214 + sirfsoc_timer_count_disable(1);
  215 +
  216 + remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
  217 +}
  218 +
  219 +static struct local_timer_ops sirfsoc_local_timer_ops __cpuinitdata = {
  220 + .setup = sirfsoc_local_timer_setup,
  221 + .stop = sirfsoc_local_timer_stop,
  222 +};
  223 +#endif /* CONFIG_LOCAL_TIMERS */
  224 +
  225 +static void __init sirfsoc_clockevent_init(void)
  226 +{
  227 + clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
  228 +
  229 + sirfsoc_clockevent.max_delta_ns =
  230 + clockevent_delta2ns(-2, &sirfsoc_clockevent);
  231 + sirfsoc_clockevent.min_delta_ns =
  232 + clockevent_delta2ns(2, &sirfsoc_clockevent);
  233 +
  234 + sirfsoc_clockevent.cpumask = cpumask_of(0);
  235 + clockevents_register_device(&sirfsoc_clockevent);
  236 +#ifdef CONFIG_LOCAL_TIMERS
  237 + local_timer_register(&sirfsoc_local_timer_ops);
  238 +#endif
  239 +}
  240 +
  241 +/* initialize the kernel jiffy timer source */
  242 +static void __init sirfsoc_marco_timer_init(void)
  243 +{
  244 + unsigned long rate;
  245 + u32 timer_div;
  246 + struct clk *clk;
  247 +
  248 + /* timer's input clock is io clock */
  249 + clk = clk_get_sys("io", NULL);
  250 +
  251 + BUG_ON(IS_ERR(clk));
  252 + rate = clk_get_rate(clk);
  253 +
  254 + BUG_ON(rate < CLOCK_TICK_RATE);
  255 + BUG_ON(rate % CLOCK_TICK_RATE);
  256 +
  257 + /* Initialize the timer dividers */
  258 + timer_div = rate / CLOCK_TICK_RATE - 1;
  259 + writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
  260 + writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
  261 + writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
  262 +
  263 + /* Initialize timer counters to 0 */
  264 + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
  265 + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
  266 + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
  267 + BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
  268 + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0);
  269 + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1);
  270 +
  271 + /* Clear all interrupts */
  272 + writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
  273 +
  274 + BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
  275 +
  276 + BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
  277 +
  278 + sirfsoc_clockevent_init();
  279 +}
  280 +
  281 +static void __init sirfsoc_of_timer_init(struct device_node *np)
  282 +{
  283 + sirfsoc_timer_base = of_iomap(np, 0);
  284 + if (!sirfsoc_timer_base)
  285 + panic("unable to map timer cpu registers\n");
  286 +
  287 + sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
  288 + if (!sirfsoc_timer_irq.irq)
  289 + panic("No irq passed for timer0 via DT\n");
  290 +
  291 +#ifdef CONFIG_LOCAL_TIMERS
  292 + sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1);
  293 + if (!sirfsoc_timer1_irq.irq)
  294 + panic("No irq passed for timer1 via DT\n");
  295 +#endif
  296 +
  297 + sirfsoc_marco_timer_init();
  298 +}
  299 +CLOCKSOURCE_OF_DECLARE(sirfsoc_marco_timer, "sirf,marco-tick", sirfsoc_of_timer_init );
drivers/clocksource/timer-prima2.c
  1 +/*
  2 + * System timer for CSR SiRFprimaII
  3 + *
  4 + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
  5 + *
  6 + * Licensed under GPLv2 or later.
  7 + */
  8 +
  9 +#include <linux/kernel.h>
  10 +#include <linux/interrupt.h>
  11 +#include <linux/clockchips.h>
  12 +#include <linux/clocksource.h>
  13 +#include <linux/bitops.h>
  14 +#include <linux/irq.h>
  15 +#include <linux/clk.h>
  16 +#include <linux/err.h>
  17 +#include <linux/slab.h>
  18 +#include <linux/of.h>
  19 +#include <linux/of_irq.h>
  20 +#include <linux/of_address.h>
  21 +#include <asm/sched_clock.h>
  22 +#include <asm/mach/time.h>
  23 +
  24 +#define SIRFSOC_TIMER_COUNTER_LO 0x0000
  25 +#define SIRFSOC_TIMER_COUNTER_HI 0x0004
  26 +#define SIRFSOC_TIMER_MATCH_0 0x0008
  27 +#define SIRFSOC_TIMER_MATCH_1 0x000C
  28 +#define SIRFSOC_TIMER_MATCH_2 0x0010
  29 +#define SIRFSOC_TIMER_MATCH_3 0x0014
  30 +#define SIRFSOC_TIMER_MATCH_4 0x0018
  31 +#define SIRFSOC_TIMER_MATCH_5 0x001C
  32 +#define SIRFSOC_TIMER_STATUS 0x0020
  33 +#define SIRFSOC_TIMER_INT_EN 0x0024
  34 +#define SIRFSOC_TIMER_WATCHDOG_EN 0x0028
  35 +#define SIRFSOC_TIMER_DIV 0x002C
  36 +#define SIRFSOC_TIMER_LATCH 0x0030
  37 +#define SIRFSOC_TIMER_LATCHED_LO 0x0034
  38 +#define SIRFSOC_TIMER_LATCHED_HI 0x0038
  39 +
  40 +#define SIRFSOC_TIMER_WDT_INDEX 5
  41 +
  42 +#define SIRFSOC_TIMER_LATCH_BIT BIT(0)
  43 +
  44 +#define SIRFSOC_TIMER_REG_CNT 11
  45 +
  46 +static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
  47 + SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
  48 + SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
  49 + SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
  50 + SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
  51 +};
  52 +
  53 +static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
  54 +
  55 +static void __iomem *sirfsoc_timer_base;
  56 +
  57 +/* timer0 interrupt handler */
  58 +static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
  59 +{
  60 + struct clock_event_device *ce = dev_id;
  61 +
  62 + WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0)));
  63 +
  64 + /* clear timer0 interrupt */
  65 + writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
  66 +
  67 + ce->event_handler(ce);
  68 +
  69 + return IRQ_HANDLED;
  70 +}
  71 +
  72 +/* read 64-bit timer counter */
  73 +static cycle_t sirfsoc_timer_read(struct clocksource *cs)
  74 +{
  75 + u64 cycles;
  76 +
  77 + /* latch the 64-bit timer counter */
  78 + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
  79 + cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI);
  80 + cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
  81 +
  82 + return cycles;
  83 +}
  84 +
  85 +static int sirfsoc_timer_set_next_event(unsigned long delta,
  86 + struct clock_event_device *ce)
  87 +{
  88 + unsigned long now, next;
  89 +
  90 + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
  91 + now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
  92 + next = now + delta;
  93 + writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0);
  94 + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
  95 + now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
  96 +
  97 + return next - now > delta ? -ETIME : 0;
  98 +}
  99 +
  100 +static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
  101 + struct clock_event_device *ce)
  102 +{
  103 + u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
  104 + switch (mode) {
  105 + case CLOCK_EVT_MODE_PERIODIC:
  106 + WARN_ON(1);
  107 + break;
  108 + case CLOCK_EVT_MODE_ONESHOT:
  109 + writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
  110 + break;
  111 + case CLOCK_EVT_MODE_SHUTDOWN:
  112 + writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
  113 + break;
  114 + case CLOCK_EVT_MODE_UNUSED:
  115 + case CLOCK_EVT_MODE_RESUME:
  116 + break;
  117 + }
  118 +}
  119 +
  120 +static void sirfsoc_clocksource_suspend(struct clocksource *cs)
  121 +{
  122 + int i;
  123 +
  124 + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
  125 +
  126 + for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
  127 + sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
  128 +}
  129 +
  130 +static void sirfsoc_clocksource_resume(struct clocksource *cs)
  131 +{
  132 + int i;
  133 +
  134 + for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
  135 + writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
  136 +
  137 + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
  138 + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
  139 +}
  140 +
  141 +static struct clock_event_device sirfsoc_clockevent = {
  142 + .name = "sirfsoc_clockevent",
  143 + .rating = 200,
  144 + .features = CLOCK_EVT_FEAT_ONESHOT,
  145 + .set_mode = sirfsoc_timer_set_mode,
  146 + .set_next_event = sirfsoc_timer_set_next_event,
  147 +};
  148 +
  149 +static struct clocksource sirfsoc_clocksource = {
  150 + .name = "sirfsoc_clocksource",
  151 + .rating = 200,
  152 + .mask = CLOCKSOURCE_MASK(64),
  153 + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  154 + .read = sirfsoc_timer_read,
  155 + .suspend = sirfsoc_clocksource_suspend,
  156 + .resume = sirfsoc_clocksource_resume,
  157 +};
  158 +
  159 +static struct irqaction sirfsoc_timer_irq = {
  160 + .name = "sirfsoc_timer0",
  161 + .flags = IRQF_TIMER,
  162 + .irq = 0,
  163 + .handler = sirfsoc_timer_interrupt,
  164 + .dev_id = &sirfsoc_clockevent,
  165 +};
  166 +
  167 +/* Overwrite weak default sched_clock with more precise one */
  168 +static u32 notrace sirfsoc_read_sched_clock(void)
  169 +{
  170 + return (u32)(sirfsoc_timer_read(NULL) & 0xffffffff);
  171 +}
  172 +
  173 +static void __init sirfsoc_clockevent_init(void)
  174 +{
  175 + sirfsoc_clockevent.cpumask = cpumask_of(0);
  176 + clockevents_config_and_register(&sirfsoc_clockevent, CLOCK_TICK_RATE,
  177 + 2, -2);
  178 +}
  179 +
  180 +/* initialize the kernel jiffy timer source */
  181 +static void __init sirfsoc_prima2_timer_init(struct device_node *np)
  182 +{
  183 + unsigned long rate;
  184 + struct clk *clk;
  185 +
  186 + /* timer's input clock is io clock */
  187 + clk = clk_get_sys("io", NULL);
  188 +
  189 + BUG_ON(IS_ERR(clk));
  190 +
  191 + rate = clk_get_rate(clk);
  192 +
  193 + BUG_ON(rate < CLOCK_TICK_RATE);
  194 + BUG_ON(rate % CLOCK_TICK_RATE);
  195 +
  196 + sirfsoc_timer_base = of_iomap(np, 0);
  197 + if (!sirfsoc_timer_base)
  198 + panic("unable to map timer cpu registers\n");
  199 +
  200 + sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
  201 +
  202 + writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
  203 + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
  204 + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
  205 + writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
  206 +
  207 + BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
  208 +
  209 + setup_sched_clock(sirfsoc_read_sched_clock, 32, CLOCK_TICK_RATE);
  210 +
  211 + BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
  212 +
  213 + sirfsoc_clockevent_init();
  214 +}
  215 +CLOCKSOURCE_OF_DECLARE(sirfsoc_prima2_timer, "sirf,prima2-tick", sirfsoc_prima2_timer_init);