clocksource/drivers/fttmr010: Switch to use TIMER2 src
[linux-2.6-block.git] / drivers / clocksource / timer-fttmr010.c
1 /*
2  * Faraday Technology FTTMR010 timer driver
3  * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
4  *
5  * Based on a rewrite of arch/arm/mach-gemini/timer.c:
6  * Copyright (C) 2001-2006 Storlink, Corp.
7  * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
8  */
9 #include <linux/interrupt.h>
10 #include <linux/io.h>
11 #include <linux/of.h>
12 #include <linux/of_address.h>
13 #include <linux/of_irq.h>
14 #include <linux/clockchips.h>
15 #include <linux/clocksource.h>
16 #include <linux/sched_clock.h>
17 #include <linux/clk.h>
18 #include <linux/slab.h>
19 #include <linux/bitops.h>
20
21 /*
22  * Register definitions for the timers
23  */
24 #define TIMER1_COUNT            (0x00)
25 #define TIMER1_LOAD             (0x04)
26 #define TIMER1_MATCH1           (0x08)
27 #define TIMER1_MATCH2           (0x0c)
28 #define TIMER2_COUNT            (0x10)
29 #define TIMER2_LOAD             (0x14)
30 #define TIMER2_MATCH1           (0x18)
31 #define TIMER2_MATCH2           (0x1c)
32 #define TIMER3_COUNT            (0x20)
33 #define TIMER3_LOAD             (0x24)
34 #define TIMER3_MATCH1           (0x28)
35 #define TIMER3_MATCH2           (0x2c)
36 #define TIMER_CR                (0x30)
37 #define TIMER_INTR_STATE        (0x34)
38 #define TIMER_INTR_MASK         (0x38)
39
40 #define TIMER_1_CR_ENABLE       BIT(0)
41 #define TIMER_1_CR_CLOCK        BIT(1)
42 #define TIMER_1_CR_INT          BIT(2)
43 #define TIMER_2_CR_ENABLE       BIT(3)
44 #define TIMER_2_CR_CLOCK        BIT(4)
45 #define TIMER_2_CR_INT          BIT(5)
46 #define TIMER_3_CR_ENABLE       BIT(6)
47 #define TIMER_3_CR_CLOCK        BIT(7)
48 #define TIMER_3_CR_INT          BIT(8)
49 #define TIMER_1_CR_UPDOWN       BIT(9)
50 #define TIMER_2_CR_UPDOWN       BIT(10)
51 #define TIMER_3_CR_UPDOWN       BIT(11)
52
53 #define TIMER_1_INT_MATCH1      BIT(0)
54 #define TIMER_1_INT_MATCH2      BIT(1)
55 #define TIMER_1_INT_OVERFLOW    BIT(2)
56 #define TIMER_2_INT_MATCH1      BIT(3)
57 #define TIMER_2_INT_MATCH2      BIT(4)
58 #define TIMER_2_INT_OVERFLOW    BIT(5)
59 #define TIMER_3_INT_MATCH1      BIT(6)
60 #define TIMER_3_INT_MATCH2      BIT(7)
61 #define TIMER_3_INT_OVERFLOW    BIT(8)
62 #define TIMER_INT_ALL_MASK      0x1ff
63
64 struct fttmr010 {
65         void __iomem *base;
66         unsigned int tick_rate;
67         struct clock_event_device clkevt;
68 };
69
70 /* A local singleton used by sched_clock, which is stateless */
71 static struct fttmr010 *local_fttmr;
72
73 static inline struct fttmr010 *to_fttmr010(struct clock_event_device *evt)
74 {
75         return container_of(evt, struct fttmr010, clkevt);
76 }
77
78 static u64 notrace fttmr010_read_sched_clock(void)
79 {
80         return readl(local_fttmr->base + TIMER2_COUNT);
81 }
82
83 static int fttmr010_timer_set_next_event(unsigned long cycles,
84                                        struct clock_event_device *evt)
85 {
86         struct fttmr010 *fttmr010 = to_fttmr010(evt);
87         u32 cr;
88
89         /* Setup the match register */
90         cr = readl(fttmr010->base + TIMER1_COUNT);
91         writel(cr + cycles, fttmr010->base + TIMER1_MATCH1);
92         if (readl(fttmr010->base + TIMER1_COUNT) - cr > cycles)
93                 return -ETIME;
94
95         return 0;
96 }
97
98 static int fttmr010_timer_shutdown(struct clock_event_device *evt)
99 {
100         struct fttmr010 *fttmr010 = to_fttmr010(evt);
101         u32 cr;
102
103         /* Stop timer and interrupt. */
104         cr = readl(fttmr010->base + TIMER_CR);
105         cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
106         writel(cr, fttmr010->base + TIMER_CR);
107
108         return 0;
109 }
110
111 static int fttmr010_timer_set_oneshot(struct clock_event_device *evt)
112 {
113         struct fttmr010 *fttmr010 = to_fttmr010(evt);
114         u32 cr;
115
116         /* Stop timer and interrupt. */
117         cr = readl(fttmr010->base + TIMER_CR);
118         cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
119         writel(cr, fttmr010->base + TIMER_CR);
120
121         /* Setup counter start from 0 */
122         writel(0, fttmr010->base + TIMER1_COUNT);
123         writel(0, fttmr010->base + TIMER1_LOAD);
124
125         /* Enable interrupt */
126         cr = readl(fttmr010->base + TIMER_INTR_MASK);
127         cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);
128         cr |= TIMER_1_INT_MATCH1;
129         writel(cr, fttmr010->base + TIMER_INTR_MASK);
130
131         /* Start the timer */
132         cr = readl(fttmr010->base + TIMER_CR);
133         cr |= TIMER_1_CR_ENABLE;
134         writel(cr, fttmr010->base + TIMER_CR);
135
136         return 0;
137 }
138
139 static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
140 {
141         struct fttmr010 *fttmr010 = to_fttmr010(evt);
142         u32 period = DIV_ROUND_CLOSEST(fttmr010->tick_rate, HZ);
143         u32 cr;
144
145         /* Stop timer and interrupt */
146         cr = readl(fttmr010->base + TIMER_CR);
147         cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
148         writel(cr, fttmr010->base + TIMER_CR);
149
150         /* Setup timer to fire at 1/HT intervals. */
151         cr = 0xffffffff - (period - 1);
152         writel(cr, fttmr010->base + TIMER1_COUNT);
153         writel(cr, fttmr010->base + TIMER1_LOAD);
154
155         /* enable interrupt on overflow */
156         cr = readl(fttmr010->base + TIMER_INTR_MASK);
157         cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
158         cr |= TIMER_1_INT_OVERFLOW;
159         writel(cr, fttmr010->base + TIMER_INTR_MASK);
160
161         /* Start the timer */
162         cr = readl(fttmr010->base + TIMER_CR);
163         cr |= TIMER_1_CR_ENABLE;
164         cr |= TIMER_1_CR_INT;
165         writel(cr, fttmr010->base + TIMER_CR);
166
167         return 0;
168 }
169
170 /*
171  * IRQ handler for the timer
172  */
173 static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id)
174 {
175         struct clock_event_device *evt = dev_id;
176
177         evt->event_handler(evt);
178         return IRQ_HANDLED;
179 }
180
181 static int __init fttmr010_timer_init(struct device_node *np)
182 {
183         struct fttmr010 *fttmr010;
184         int irq;
185         struct clk *clk;
186         int ret;
187
188         /*
189          * These implementations require a clock reference.
190          * FIXME: we currently only support clocking using PCLK
191          * and using EXTCLK is not supported in the driver.
192          */
193         clk = of_clk_get_by_name(np, "PCLK");
194         if (IS_ERR(clk)) {
195                 pr_err("could not get PCLK\n");
196                 return PTR_ERR(clk);
197         }
198         ret = clk_prepare_enable(clk);
199         if (ret) {
200                 pr_err("failed to enable PCLK\n");
201                 return ret;
202         }
203
204         fttmr010 = kzalloc(sizeof(*fttmr010), GFP_KERNEL);
205         if (!fttmr010) {
206                 ret = -ENOMEM;
207                 goto out_disable_clock;
208         }
209         fttmr010->tick_rate = clk_get_rate(clk);
210
211         fttmr010->base = of_iomap(np, 0);
212         if (!fttmr010->base) {
213                 pr_err("Can't remap registers");
214                 ret = -ENXIO;
215                 goto out_free;
216         }
217         /* IRQ for timer 1 */
218         irq = irq_of_parse_and_map(np, 0);
219         if (irq <= 0) {
220                 pr_err("Can't parse IRQ");
221                 ret = -EINVAL;
222                 goto out_unmap;
223         }
224
225         /*
226          * Reset the interrupt mask and status
227          */
228         writel(TIMER_INT_ALL_MASK, fttmr010->base + TIMER_INTR_MASK);
229         writel(0, fttmr010->base + TIMER_INTR_STATE);
230         /* Enable timer 1 count up, timer 2 count up */
231         writel((TIMER_1_CR_UPDOWN | TIMER_2_CR_ENABLE | TIMER_2_CR_UPDOWN),
232                fttmr010->base + TIMER_CR);
233
234         /*
235          * Setup free-running clocksource timer (interrupts
236          * disabled.)
237          */
238         local_fttmr = fttmr010;
239         writel(0, fttmr010->base + TIMER2_COUNT);
240         writel(0, fttmr010->base + TIMER2_LOAD);
241         writel(0, fttmr010->base + TIMER2_MATCH1);
242         writel(0, fttmr010->base + TIMER2_MATCH2);
243         clocksource_mmio_init(fttmr010->base + TIMER2_COUNT,
244                               "FTTMR010-TIMER2",
245                               fttmr010->tick_rate,
246                               300, 32, clocksource_mmio_readl_up);
247         sched_clock_register(fttmr010_read_sched_clock, 32,
248                              fttmr010->tick_rate);
249
250         /*
251          * Setup clockevent timer (interrupt-driven) on timer 1.
252          */
253         writel(0, fttmr010->base + TIMER1_COUNT);
254         writel(0, fttmr010->base + TIMER1_LOAD);
255         writel(0, fttmr010->base + TIMER1_MATCH1);
256         writel(0, fttmr010->base + TIMER1_MATCH2);
257         ret = request_irq(irq, fttmr010_timer_interrupt, IRQF_TIMER,
258                           "FTTMR010-TIMER1", &fttmr010->clkevt);
259         if (ret) {
260                 pr_err("FTTMR010-TIMER1 no IRQ\n");
261                 goto out_unmap;
262         }
263
264         fttmr010->clkevt.name = "FTTMR010-TIMER1";
265         /* Reasonably fast and accurate clock event */
266         fttmr010->clkevt.rating = 300;
267         fttmr010->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
268                 CLOCK_EVT_FEAT_ONESHOT;
269         fttmr010->clkevt.set_next_event = fttmr010_timer_set_next_event;
270         fttmr010->clkevt.set_state_shutdown = fttmr010_timer_shutdown;
271         fttmr010->clkevt.set_state_periodic = fttmr010_timer_set_periodic;
272         fttmr010->clkevt.set_state_oneshot = fttmr010_timer_set_oneshot;
273         fttmr010->clkevt.tick_resume = fttmr010_timer_shutdown;
274         fttmr010->clkevt.cpumask = cpumask_of(0);
275         fttmr010->clkevt.irq = irq;
276         clockevents_config_and_register(&fttmr010->clkevt,
277                                         fttmr010->tick_rate,
278                                         1, 0xffffffff);
279
280         return 0;
281
282 out_unmap:
283         iounmap(fttmr010->base);
284 out_free:
285         kfree(fttmr010);
286 out_disable_clock:
287         clk_disable_unprepare(clk);
288
289         return ret;
290 }
291 CLOCKSOURCE_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init);
292 CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", fttmr010_timer_init);