2 * Faraday Technology FTTMR010 timer driver
3 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
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>
9 #include <linux/interrupt.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>
22 * Register definitions for the timers
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)
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)
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
66 unsigned int tick_rate;
67 struct clock_event_device clkevt;
70 /* A local singleton used by sched_clock, which is stateless */
71 static struct fttmr010 *local_fttmr;
73 static inline struct fttmr010 *to_fttmr010(struct clock_event_device *evt)
75 return container_of(evt, struct fttmr010, clkevt);
78 static u64 notrace fttmr010_read_sched_clock(void)
80 return readl(local_fttmr->base + TIMER2_COUNT);
83 static int fttmr010_timer_set_next_event(unsigned long cycles,
84 struct clock_event_device *evt)
86 struct fttmr010 *fttmr010 = to_fttmr010(evt);
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)
98 static int fttmr010_timer_shutdown(struct clock_event_device *evt)
100 struct fttmr010 *fttmr010 = to_fttmr010(evt);
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);
111 static int fttmr010_timer_set_oneshot(struct clock_event_device *evt)
113 struct fttmr010 *fttmr010 = to_fttmr010(evt);
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);
121 /* Setup counter start from 0 */
122 writel(0, fttmr010->base + TIMER1_COUNT);
123 writel(0, fttmr010->base + TIMER1_LOAD);
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);
131 /* Start the timer */
132 cr = readl(fttmr010->base + TIMER_CR);
133 cr |= TIMER_1_CR_ENABLE;
134 writel(cr, fttmr010->base + TIMER_CR);
139 static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
141 struct fttmr010 *fttmr010 = to_fttmr010(evt);
142 u32 period = DIV_ROUND_CLOSEST(fttmr010->tick_rate, HZ);
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);
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);
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);
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);
171 * IRQ handler for the timer
173 static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id)
175 struct clock_event_device *evt = dev_id;
177 evt->event_handler(evt);
181 static int __init fttmr010_timer_init(struct device_node *np)
183 struct fttmr010 *fttmr010;
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.
193 clk = of_clk_get_by_name(np, "PCLK");
195 pr_err("could not get PCLK\n");
198 ret = clk_prepare_enable(clk);
200 pr_err("failed to enable PCLK\n");
204 fttmr010 = kzalloc(sizeof(*fttmr010), GFP_KERNEL);
207 goto out_disable_clock;
209 fttmr010->tick_rate = clk_get_rate(clk);
211 fttmr010->base = of_iomap(np, 0);
212 if (!fttmr010->base) {
213 pr_err("Can't remap registers");
217 /* IRQ for timer 1 */
218 irq = irq_of_parse_and_map(np, 0);
220 pr_err("Can't parse IRQ");
226 * Reset the interrupt mask and status
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);
235 * Setup free-running clocksource timer (interrupts
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,
246 300, 32, clocksource_mmio_readl_up);
247 sched_clock_register(fttmr010_read_sched_clock, 32,
248 fttmr010->tick_rate);
251 * Setup clockevent timer (interrupt-driven) on timer 1.
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);
260 pr_err("FTTMR010-TIMER1 no IRQ\n");
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,
283 iounmap(fttmr010->base);
287 clk_disable_unprepare(clk);
291 CLOCKSOURCE_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init);
292 CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", fttmr010_timer_init);