]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/blob - arch/arm/mach-zynq/timer.c
Merge branch 'akpm' (Andrew's patch-bomb)
[can-eth-gw-linux.git] / arch / arm / mach-zynq / timer.c
1 /*
2  * This file contains driver for the Xilinx PS Timer Counter IP.
3  *
4  *  Copyright (C) 2011 Xilinx
5  *
6  * based on arch/mips/kernel/time.c timer driver
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  */
17
18 #include <linux/kernel.h>
19 #include <linux/init.h>
20 #include <linux/interrupt.h>
21 #include <linux/irq.h>
22 #include <linux/types.h>
23 #include <linux/clocksource.h>
24 #include <linux/clockchips.h>
25 #include <linux/io.h>
26 #include <linux/of.h>
27 #include <linux/of_address.h>
28 #include <linux/of_irq.h>
29 #include <linux/slab.h>
30 #include <linux/clk-provider.h>
31
32 #include "common.h"
33
34 /*
35  * Timer Register Offset Definitions of Timer 1, Increment base address by 4
36  * and use same offsets for Timer 2
37  */
38 #define XTTCPSS_CLK_CNTRL_OFFSET        0x00 /* Clock Control Reg, RW */
39 #define XTTCPSS_CNT_CNTRL_OFFSET        0x0C /* Counter Control Reg, RW */
40 #define XTTCPSS_COUNT_VAL_OFFSET        0x18 /* Counter Value Reg, RO */
41 #define XTTCPSS_INTR_VAL_OFFSET         0x24 /* Interval Count Reg, RW */
42 #define XTTCPSS_MATCH_1_OFFSET          0x30 /* Match 1 Value Reg, RW */
43 #define XTTCPSS_MATCH_2_OFFSET          0x3C /* Match 2 Value Reg, RW */
44 #define XTTCPSS_MATCH_3_OFFSET          0x48 /* Match 3 Value Reg, RW */
45 #define XTTCPSS_ISR_OFFSET              0x54 /* Interrupt Status Reg, RO */
46 #define XTTCPSS_IER_OFFSET              0x60 /* Interrupt Enable Reg, RW */
47
48 #define XTTCPSS_CNT_CNTRL_DISABLE_MASK  0x1
49
50 /* Setup the timers to use pre-scaling, using a fixed value for now that will
51  * work across most input frequency, but it may need to be more dynamic
52  */
53 #define PRESCALE_EXPONENT       11      /* 2 ^ PRESCALE_EXPONENT = PRESCALE */
54 #define PRESCALE                2048    /* The exponent must match this */
55 #define CLK_CNTRL_PRESCALE      ((PRESCALE_EXPONENT - 1) << 1)
56 #define CLK_CNTRL_PRESCALE_EN   1
57 #define CNT_CNTRL_RESET         (1<<4)
58
59 /**
60  * struct xttcpss_timer - This definition defines local timer structure
61  *
62  * @base_addr:  Base address of timer
63  **/
64 struct xttcpss_timer {
65         void __iomem    *base_addr;
66 };
67
68 struct xttcpss_timer_clocksource {
69         struct xttcpss_timer    xttc;
70         struct clocksource      cs;
71 };
72
73 #define to_xttcpss_timer_clksrc(x) \
74                 container_of(x, struct xttcpss_timer_clocksource, cs)
75
76 struct xttcpss_timer_clockevent {
77         struct xttcpss_timer            xttc;
78         struct clock_event_device       ce;
79         struct clk                      *clk;
80 };
81
82 #define to_xttcpss_timer_clkevent(x) \
83                 container_of(x, struct xttcpss_timer_clockevent, ce)
84
85 /**
86  * xttcpss_set_interval - Set the timer interval value
87  *
88  * @timer:      Pointer to the timer instance
89  * @cycles:     Timer interval ticks
90  **/
91 static void xttcpss_set_interval(struct xttcpss_timer *timer,
92                                         unsigned long cycles)
93 {
94         u32 ctrl_reg;
95
96         /* Disable the counter, set the counter value  and re-enable counter */
97         ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
98         ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
99         __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
100
101         __raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET);
102
103         /* Reset the counter (0x10) so that it starts from 0, one-shot
104            mode makes this needed for timing to be right. */
105         ctrl_reg |= CNT_CNTRL_RESET;
106         ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
107         __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
108 }
109
110 /**
111  * xttcpss_clock_event_interrupt - Clock event timer interrupt handler
112  *
113  * @irq:        IRQ number of the Timer
114  * @dev_id:     void pointer to the xttcpss_timer instance
115  *
116  * returns: Always IRQ_HANDLED - success
117  **/
118 static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
119 {
120         struct xttcpss_timer_clockevent *xttce = dev_id;
121         struct xttcpss_timer *timer = &xttce->xttc;
122
123         /* Acknowledge the interrupt and call event handler */
124         __raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
125                         timer->base_addr + XTTCPSS_ISR_OFFSET);
126
127         xttce->ce.event_handler(&xttce->ce);
128
129         return IRQ_HANDLED;
130 }
131
132 /**
133  * __xttc_clocksource_read - Reads the timer counter register
134  *
135  * returns: Current timer counter register value
136  **/
137 static cycle_t __xttc_clocksource_read(struct clocksource *cs)
138 {
139         struct xttcpss_timer *timer = &to_xttcpss_timer_clksrc(cs)->xttc;
140
141         return (cycle_t)__raw_readl(timer->base_addr +
142                                 XTTCPSS_COUNT_VAL_OFFSET);
143 }
144
145 /**
146  * xttcpss_set_next_event - Sets the time interval for next event
147  *
148  * @cycles:     Timer interval ticks
149  * @evt:        Address of clock event instance
150  *
151  * returns: Always 0 - success
152  **/
153 static int xttcpss_set_next_event(unsigned long cycles,
154                                         struct clock_event_device *evt)
155 {
156         struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt);
157         struct xttcpss_timer *timer = &xttce->xttc;
158
159         xttcpss_set_interval(timer, cycles);
160         return 0;
161 }
162
163 /**
164  * xttcpss_set_mode - Sets the mode of timer
165  *
166  * @mode:       Mode to be set
167  * @evt:        Address of clock event instance
168  **/
169 static void xttcpss_set_mode(enum clock_event_mode mode,
170                                         struct clock_event_device *evt)
171 {
172         struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt);
173         struct xttcpss_timer *timer = &xttce->xttc;
174         u32 ctrl_reg;
175
176         switch (mode) {
177         case CLOCK_EVT_MODE_PERIODIC:
178                 xttcpss_set_interval(timer,
179                                      DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk),
180                                                        PRESCALE * HZ));
181                 break;
182         case CLOCK_EVT_MODE_ONESHOT:
183         case CLOCK_EVT_MODE_UNUSED:
184         case CLOCK_EVT_MODE_SHUTDOWN:
185                 ctrl_reg = __raw_readl(timer->base_addr +
186                                         XTTCPSS_CNT_CNTRL_OFFSET);
187                 ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
188                 __raw_writel(ctrl_reg,
189                                 timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
190                 break;
191         case CLOCK_EVT_MODE_RESUME:
192                 ctrl_reg = __raw_readl(timer->base_addr +
193                                         XTTCPSS_CNT_CNTRL_OFFSET);
194                 ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
195                 __raw_writel(ctrl_reg,
196                                 timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
197                 break;
198         }
199 }
200
201 static void __init zynq_ttc_setup_clocksource(struct device_node *np,
202                                              void __iomem *base)
203 {
204         struct xttcpss_timer_clocksource *ttccs;
205         struct clk *clk;
206         int err;
207         u32 reg;
208
209         ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL);
210         if (WARN_ON(!ttccs))
211                 return;
212
213         err = of_property_read_u32(np, "reg", &reg);
214         if (WARN_ON(err))
215                 return;
216
217         clk = of_clk_get_by_name(np, "cpu_1x");
218         if (WARN_ON(IS_ERR(clk)))
219                 return;
220
221         err = clk_prepare_enable(clk);
222         if (WARN_ON(err))
223                 return;
224
225         ttccs->xttc.base_addr = base + reg * 4;
226
227         ttccs->cs.name = np->name;
228         ttccs->cs.rating = 200;
229         ttccs->cs.read = __xttc_clocksource_read;
230         ttccs->cs.mask = CLOCKSOURCE_MASK(16);
231         ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
232
233         __raw_writel(0x0,  ttccs->xttc.base_addr + XTTCPSS_IER_OFFSET);
234         __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
235                      ttccs->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET);
236         __raw_writel(CNT_CNTRL_RESET,
237                      ttccs->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
238
239         err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE);
240         if (WARN_ON(err))
241                 return;
242 }
243
244 static void __init zynq_ttc_setup_clockevent(struct device_node *np,
245                                             void __iomem *base)
246 {
247         struct xttcpss_timer_clockevent *ttcce;
248         int err, irq;
249         u32 reg;
250
251         ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
252         if (WARN_ON(!ttcce))
253                 return;
254
255         err = of_property_read_u32(np, "reg", &reg);
256         if (WARN_ON(err))
257                 return;
258
259         ttcce->xttc.base_addr = base + reg * 4;
260
261         ttcce->clk = of_clk_get_by_name(np, "cpu_1x");
262         if (WARN_ON(IS_ERR(ttcce->clk)))
263                 return;
264
265         err = clk_prepare_enable(ttcce->clk);
266         if (WARN_ON(err))
267                 return;
268
269         irq = irq_of_parse_and_map(np, 0);
270         if (WARN_ON(!irq))
271                 return;
272
273         ttcce->ce.name = np->name;
274         ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
275         ttcce->ce.set_next_event = xttcpss_set_next_event;
276         ttcce->ce.set_mode = xttcpss_set_mode;
277         ttcce->ce.rating = 200;
278         ttcce->ce.irq = irq;
279
280         __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
281         __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
282                      ttcce->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET);
283         __raw_writel(0x1,  ttcce->xttc.base_addr + XTTCPSS_IER_OFFSET);
284
285         err = request_irq(irq, xttcpss_clock_event_interrupt, IRQF_TIMER,
286                           np->name, ttcce);
287         if (WARN_ON(err))
288                 return;
289
290         clockevents_config_and_register(&ttcce->ce,
291                                         clk_get_rate(ttcce->clk) / PRESCALE,
292                                         1, 0xfffe);
293 }
294
295 static const __initconst struct of_device_id zynq_ttc_match[] = {
296         { .compatible = "xlnx,ttc-counter-clocksource",
297                 .data = zynq_ttc_setup_clocksource, },
298         { .compatible = "xlnx,ttc-counter-clockevent",
299                 .data = zynq_ttc_setup_clockevent, },
300         {}
301 };
302
303 /**
304  * xttcpss_timer_init - Initialize the timer
305  *
306  * Initializes the timer hardware and register the clock source and clock event
307  * timers with Linux kernal timer framework
308  **/
309 void __init xttcpss_timer_init(void)
310 {
311         struct device_node *np;
312
313         for_each_compatible_node(np, NULL, "xlnx,ttc") {
314                 struct device_node *np_chld;
315                 void __iomem *base;
316
317                 base = of_iomap(np, 0);
318                 if (WARN_ON(!base))
319                         return;
320
321                 for_each_available_child_of_node(np, np_chld) {
322                         int (*cb)(struct device_node *np, void __iomem *base);
323                         const struct of_device_id *match;
324
325                         match = of_match_node(zynq_ttc_match, np_chld);
326                         if (match) {
327                                 cb = match->data;
328                                 cb(np_chld, base);
329                         }
330                 }
331         }
332 }