1*f5bf0ee4SLinus Walleij /*
2*f5bf0ee4SLinus Walleij  * Faraday Technology FTTMR010 timer driver
3*f5bf0ee4SLinus Walleij  * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
4*f5bf0ee4SLinus Walleij  *
5*f5bf0ee4SLinus Walleij  * Based on a rewrite of arch/arm/mach-gemini/timer.c:
6*f5bf0ee4SLinus Walleij  * Copyright (C) 2001-2006 Storlink, Corp.
7*f5bf0ee4SLinus Walleij  * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
8*f5bf0ee4SLinus Walleij  */
9*f5bf0ee4SLinus Walleij #include <linux/interrupt.h>
10*f5bf0ee4SLinus Walleij #include <linux/io.h>
11*f5bf0ee4SLinus Walleij #include <linux/of.h>
12*f5bf0ee4SLinus Walleij #include <linux/of_address.h>
13*f5bf0ee4SLinus Walleij #include <linux/of_irq.h>
14*f5bf0ee4SLinus Walleij #include <linux/mfd/syscon.h>
15*f5bf0ee4SLinus Walleij #include <linux/regmap.h>
16*f5bf0ee4SLinus Walleij #include <linux/clockchips.h>
17*f5bf0ee4SLinus Walleij #include <linux/clocksource.h>
18*f5bf0ee4SLinus Walleij #include <linux/sched_clock.h>
19*f5bf0ee4SLinus Walleij 
20*f5bf0ee4SLinus Walleij /*
21*f5bf0ee4SLinus Walleij  * Relevant registers in the global syscon
22*f5bf0ee4SLinus Walleij  */
23*f5bf0ee4SLinus Walleij #define GLOBAL_STATUS		0x04
24*f5bf0ee4SLinus Walleij #define CPU_AHB_RATIO_MASK	(0x3 << 18)
25*f5bf0ee4SLinus Walleij #define CPU_AHB_1_1		(0x0 << 18)
26*f5bf0ee4SLinus Walleij #define CPU_AHB_3_2		(0x1 << 18)
27*f5bf0ee4SLinus Walleij #define CPU_AHB_24_13		(0x2 << 18)
28*f5bf0ee4SLinus Walleij #define CPU_AHB_2_1		(0x3 << 18)
29*f5bf0ee4SLinus Walleij #define REG_TO_AHB_SPEED(reg)	((((reg) >> 15) & 0x7) * 10 + 130)
30*f5bf0ee4SLinus Walleij 
31*f5bf0ee4SLinus Walleij /*
32*f5bf0ee4SLinus Walleij  * Register definitions for the timers
33*f5bf0ee4SLinus Walleij  */
34*f5bf0ee4SLinus Walleij #define TIMER1_COUNT		(0x00)
35*f5bf0ee4SLinus Walleij #define TIMER1_LOAD		(0x04)
36*f5bf0ee4SLinus Walleij #define TIMER1_MATCH1		(0x08)
37*f5bf0ee4SLinus Walleij #define TIMER1_MATCH2		(0x0c)
38*f5bf0ee4SLinus Walleij #define TIMER2_COUNT		(0x10)
39*f5bf0ee4SLinus Walleij #define TIMER2_LOAD		(0x14)
40*f5bf0ee4SLinus Walleij #define TIMER2_MATCH1		(0x18)
41*f5bf0ee4SLinus Walleij #define TIMER2_MATCH2		(0x1c)
42*f5bf0ee4SLinus Walleij #define TIMER3_COUNT		(0x20)
43*f5bf0ee4SLinus Walleij #define TIMER3_LOAD		(0x24)
44*f5bf0ee4SLinus Walleij #define TIMER3_MATCH1		(0x28)
45*f5bf0ee4SLinus Walleij #define TIMER3_MATCH2		(0x2c)
46*f5bf0ee4SLinus Walleij #define TIMER_CR		(0x30)
47*f5bf0ee4SLinus Walleij #define TIMER_INTR_STATE	(0x34)
48*f5bf0ee4SLinus Walleij #define TIMER_INTR_MASK		(0x38)
49*f5bf0ee4SLinus Walleij 
50*f5bf0ee4SLinus Walleij #define TIMER_1_CR_ENABLE	(1 << 0)
51*f5bf0ee4SLinus Walleij #define TIMER_1_CR_CLOCK	(1 << 1)
52*f5bf0ee4SLinus Walleij #define TIMER_1_CR_INT		(1 << 2)
53*f5bf0ee4SLinus Walleij #define TIMER_2_CR_ENABLE	(1 << 3)
54*f5bf0ee4SLinus Walleij #define TIMER_2_CR_CLOCK	(1 << 4)
55*f5bf0ee4SLinus Walleij #define TIMER_2_CR_INT		(1 << 5)
56*f5bf0ee4SLinus Walleij #define TIMER_3_CR_ENABLE	(1 << 6)
57*f5bf0ee4SLinus Walleij #define TIMER_3_CR_CLOCK	(1 << 7)
58*f5bf0ee4SLinus Walleij #define TIMER_3_CR_INT		(1 << 8)
59*f5bf0ee4SLinus Walleij #define TIMER_1_CR_UPDOWN	(1 << 9)
60*f5bf0ee4SLinus Walleij #define TIMER_2_CR_UPDOWN	(1 << 10)
61*f5bf0ee4SLinus Walleij #define TIMER_3_CR_UPDOWN	(1 << 11)
62*f5bf0ee4SLinus Walleij #define TIMER_DEFAULT_FLAGS	(TIMER_1_CR_UPDOWN | \
63*f5bf0ee4SLinus Walleij 				 TIMER_3_CR_ENABLE | \
64*f5bf0ee4SLinus Walleij 				 TIMER_3_CR_UPDOWN)
65*f5bf0ee4SLinus Walleij 
66*f5bf0ee4SLinus Walleij #define TIMER_1_INT_MATCH1	(1 << 0)
67*f5bf0ee4SLinus Walleij #define TIMER_1_INT_MATCH2	(1 << 1)
68*f5bf0ee4SLinus Walleij #define TIMER_1_INT_OVERFLOW	(1 << 2)
69*f5bf0ee4SLinus Walleij #define TIMER_2_INT_MATCH1	(1 << 3)
70*f5bf0ee4SLinus Walleij #define TIMER_2_INT_MATCH2	(1 << 4)
71*f5bf0ee4SLinus Walleij #define TIMER_2_INT_OVERFLOW	(1 << 5)
72*f5bf0ee4SLinus Walleij #define TIMER_3_INT_MATCH1	(1 << 6)
73*f5bf0ee4SLinus Walleij #define TIMER_3_INT_MATCH2	(1 << 7)
74*f5bf0ee4SLinus Walleij #define TIMER_3_INT_OVERFLOW	(1 << 8)
75*f5bf0ee4SLinus Walleij #define TIMER_INT_ALL_MASK	0x1ff
76*f5bf0ee4SLinus Walleij 
77*f5bf0ee4SLinus Walleij static unsigned int tick_rate;
78*f5bf0ee4SLinus Walleij static void __iomem *base;
79*f5bf0ee4SLinus Walleij 
80*f5bf0ee4SLinus Walleij static u64 notrace fttmr010_read_sched_clock(void)
81*f5bf0ee4SLinus Walleij {
82*f5bf0ee4SLinus Walleij 	return readl(base + TIMER3_COUNT);
83*f5bf0ee4SLinus Walleij }
84*f5bf0ee4SLinus Walleij 
85*f5bf0ee4SLinus Walleij static int fttmr010_timer_set_next_event(unsigned long cycles,
86*f5bf0ee4SLinus Walleij 				       struct clock_event_device *evt)
87*f5bf0ee4SLinus Walleij {
88*f5bf0ee4SLinus Walleij 	u32 cr;
89*f5bf0ee4SLinus Walleij 
90*f5bf0ee4SLinus Walleij 	/* Setup the match register */
91*f5bf0ee4SLinus Walleij 	cr = readl(base + TIMER1_COUNT);
92*f5bf0ee4SLinus Walleij 	writel(cr + cycles, base + TIMER1_MATCH1);
93*f5bf0ee4SLinus Walleij 	if (readl(base + TIMER1_COUNT) - cr > cycles)
94*f5bf0ee4SLinus Walleij 		return -ETIME;
95*f5bf0ee4SLinus Walleij 
96*f5bf0ee4SLinus Walleij 	return 0;
97*f5bf0ee4SLinus Walleij }
98*f5bf0ee4SLinus Walleij 
99*f5bf0ee4SLinus Walleij static int fttmr010_timer_shutdown(struct clock_event_device *evt)
100*f5bf0ee4SLinus Walleij {
101*f5bf0ee4SLinus Walleij 	u32 cr;
102*f5bf0ee4SLinus Walleij 
103*f5bf0ee4SLinus Walleij 	/*
104*f5bf0ee4SLinus Walleij 	 * Disable also for oneshot: the set_next() call will arm the timer
105*f5bf0ee4SLinus Walleij 	 * instead.
106*f5bf0ee4SLinus Walleij 	 */
107*f5bf0ee4SLinus Walleij 	/* Stop timer and interrupt. */
108*f5bf0ee4SLinus Walleij 	cr = readl(base + TIMER_CR);
109*f5bf0ee4SLinus Walleij 	cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
110*f5bf0ee4SLinus Walleij 	writel(cr, base + TIMER_CR);
111*f5bf0ee4SLinus Walleij 
112*f5bf0ee4SLinus Walleij 	/* Setup counter start from 0 */
113*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER1_COUNT);
114*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER1_LOAD);
115*f5bf0ee4SLinus Walleij 
116*f5bf0ee4SLinus Walleij 	/* enable interrupt */
117*f5bf0ee4SLinus Walleij 	cr = readl(base + TIMER_INTR_MASK);
118*f5bf0ee4SLinus Walleij 	cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);
119*f5bf0ee4SLinus Walleij 	cr |= TIMER_1_INT_MATCH1;
120*f5bf0ee4SLinus Walleij 	writel(cr, base + TIMER_INTR_MASK);
121*f5bf0ee4SLinus Walleij 
122*f5bf0ee4SLinus Walleij 	/* start the timer */
123*f5bf0ee4SLinus Walleij 	cr = readl(base + TIMER_CR);
124*f5bf0ee4SLinus Walleij 	cr |= TIMER_1_CR_ENABLE;
125*f5bf0ee4SLinus Walleij 	writel(cr, base + TIMER_CR);
126*f5bf0ee4SLinus Walleij 
127*f5bf0ee4SLinus Walleij 	return 0;
128*f5bf0ee4SLinus Walleij }
129*f5bf0ee4SLinus Walleij 
130*f5bf0ee4SLinus Walleij static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
131*f5bf0ee4SLinus Walleij {
132*f5bf0ee4SLinus Walleij 	u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ);
133*f5bf0ee4SLinus Walleij 	u32 cr;
134*f5bf0ee4SLinus Walleij 
135*f5bf0ee4SLinus Walleij 	/* Stop timer and interrupt */
136*f5bf0ee4SLinus Walleij 	cr = readl(base + TIMER_CR);
137*f5bf0ee4SLinus Walleij 	cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
138*f5bf0ee4SLinus Walleij 	writel(cr, base + TIMER_CR);
139*f5bf0ee4SLinus Walleij 
140*f5bf0ee4SLinus Walleij 	/* Setup timer to fire at 1/HT intervals. */
141*f5bf0ee4SLinus Walleij 	cr = 0xffffffff - (period - 1);
142*f5bf0ee4SLinus Walleij 	writel(cr, base + TIMER1_COUNT);
143*f5bf0ee4SLinus Walleij 	writel(cr, base + TIMER1_LOAD);
144*f5bf0ee4SLinus Walleij 
145*f5bf0ee4SLinus Walleij 	/* enable interrupt on overflow */
146*f5bf0ee4SLinus Walleij 	cr = readl(base + TIMER_INTR_MASK);
147*f5bf0ee4SLinus Walleij 	cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
148*f5bf0ee4SLinus Walleij 	cr |= TIMER_1_INT_OVERFLOW;
149*f5bf0ee4SLinus Walleij 	writel(cr, base + TIMER_INTR_MASK);
150*f5bf0ee4SLinus Walleij 
151*f5bf0ee4SLinus Walleij 	/* Start the timer */
152*f5bf0ee4SLinus Walleij 	cr = readl(base + TIMER_CR);
153*f5bf0ee4SLinus Walleij 	cr |= TIMER_1_CR_ENABLE;
154*f5bf0ee4SLinus Walleij 	cr |= TIMER_1_CR_INT;
155*f5bf0ee4SLinus Walleij 	writel(cr, base + TIMER_CR);
156*f5bf0ee4SLinus Walleij 
157*f5bf0ee4SLinus Walleij 	return 0;
158*f5bf0ee4SLinus Walleij }
159*f5bf0ee4SLinus Walleij 
160*f5bf0ee4SLinus Walleij /* Use TIMER1 as clock event */
161*f5bf0ee4SLinus Walleij static struct clock_event_device fttmr010_clockevent = {
162*f5bf0ee4SLinus Walleij 	.name			= "TIMER1",
163*f5bf0ee4SLinus Walleij 	/* Reasonably fast and accurate clock event */
164*f5bf0ee4SLinus Walleij 	.rating			= 300,
165*f5bf0ee4SLinus Walleij 	.shift                  = 32,
166*f5bf0ee4SLinus Walleij 	.features		= CLOCK_EVT_FEAT_PERIODIC |
167*f5bf0ee4SLinus Walleij 				  CLOCK_EVT_FEAT_ONESHOT,
168*f5bf0ee4SLinus Walleij 	.set_next_event		= fttmr010_timer_set_next_event,
169*f5bf0ee4SLinus Walleij 	.set_state_shutdown	= fttmr010_timer_shutdown,
170*f5bf0ee4SLinus Walleij 	.set_state_periodic	= fttmr010_timer_set_periodic,
171*f5bf0ee4SLinus Walleij 	.set_state_oneshot	= fttmr010_timer_shutdown,
172*f5bf0ee4SLinus Walleij 	.tick_resume		= fttmr010_timer_shutdown,
173*f5bf0ee4SLinus Walleij };
174*f5bf0ee4SLinus Walleij 
175*f5bf0ee4SLinus Walleij /*
176*f5bf0ee4SLinus Walleij  * IRQ handler for the timer
177*f5bf0ee4SLinus Walleij  */
178*f5bf0ee4SLinus Walleij static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id)
179*f5bf0ee4SLinus Walleij {
180*f5bf0ee4SLinus Walleij 	struct clock_event_device *evt = &fttmr010_clockevent;
181*f5bf0ee4SLinus Walleij 
182*f5bf0ee4SLinus Walleij 	evt->event_handler(evt);
183*f5bf0ee4SLinus Walleij 	return IRQ_HANDLED;
184*f5bf0ee4SLinus Walleij }
185*f5bf0ee4SLinus Walleij 
186*f5bf0ee4SLinus Walleij static struct irqaction fttmr010_timer_irq = {
187*f5bf0ee4SLinus Walleij 	.name		= "Faraday FTTMR010 Timer Tick",
188*f5bf0ee4SLinus Walleij 	.flags		= IRQF_TIMER,
189*f5bf0ee4SLinus Walleij 	.handler	= fttmr010_timer_interrupt,
190*f5bf0ee4SLinus Walleij };
191*f5bf0ee4SLinus Walleij 
192*f5bf0ee4SLinus Walleij static int __init gemini_timer_of_init(struct device_node *np)
193*f5bf0ee4SLinus Walleij {
194*f5bf0ee4SLinus Walleij 	static struct regmap *map;
195*f5bf0ee4SLinus Walleij 	int irq;
196*f5bf0ee4SLinus Walleij 	int ret;
197*f5bf0ee4SLinus Walleij 	u32 val;
198*f5bf0ee4SLinus Walleij 
199*f5bf0ee4SLinus Walleij 	map = syscon_regmap_lookup_by_phandle(np, "syscon");
200*f5bf0ee4SLinus Walleij 	if (IS_ERR(map)) {
201*f5bf0ee4SLinus Walleij 		pr_err("Can't get regmap for syscon handle");
202*f5bf0ee4SLinus Walleij 		return -ENODEV;
203*f5bf0ee4SLinus Walleij 	}
204*f5bf0ee4SLinus Walleij 	ret = regmap_read(map, GLOBAL_STATUS, &val);
205*f5bf0ee4SLinus Walleij 	if (ret) {
206*f5bf0ee4SLinus Walleij 		pr_err("Can't read syscon status register");
207*f5bf0ee4SLinus Walleij 		return -ENXIO;
208*f5bf0ee4SLinus Walleij 	}
209*f5bf0ee4SLinus Walleij 
210*f5bf0ee4SLinus Walleij 	base = of_iomap(np, 0);
211*f5bf0ee4SLinus Walleij 	if (!base) {
212*f5bf0ee4SLinus Walleij 		pr_err("Can't remap registers");
213*f5bf0ee4SLinus Walleij 		return -ENXIO;
214*f5bf0ee4SLinus Walleij 	}
215*f5bf0ee4SLinus Walleij 	/* IRQ for timer 1 */
216*f5bf0ee4SLinus Walleij 	irq = irq_of_parse_and_map(np, 0);
217*f5bf0ee4SLinus Walleij 	if (irq <= 0) {
218*f5bf0ee4SLinus Walleij 		pr_err("Can't parse IRQ");
219*f5bf0ee4SLinus Walleij 		return -EINVAL;
220*f5bf0ee4SLinus Walleij 	}
221*f5bf0ee4SLinus Walleij 
222*f5bf0ee4SLinus Walleij 	tick_rate = REG_TO_AHB_SPEED(val) * 1000000;
223*f5bf0ee4SLinus Walleij 	printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000);
224*f5bf0ee4SLinus Walleij 
225*f5bf0ee4SLinus Walleij 	tick_rate /= 6;		/* APB bus run AHB*(1/6) */
226*f5bf0ee4SLinus Walleij 
227*f5bf0ee4SLinus Walleij 	switch (val & CPU_AHB_RATIO_MASK) {
228*f5bf0ee4SLinus Walleij 	case CPU_AHB_1_1:
229*f5bf0ee4SLinus Walleij 		printk(KERN_CONT "(1/1)\n");
230*f5bf0ee4SLinus Walleij 		break;
231*f5bf0ee4SLinus Walleij 	case CPU_AHB_3_2:
232*f5bf0ee4SLinus Walleij 		printk(KERN_CONT "(3/2)\n");
233*f5bf0ee4SLinus Walleij 		break;
234*f5bf0ee4SLinus Walleij 	case CPU_AHB_24_13:
235*f5bf0ee4SLinus Walleij 		printk(KERN_CONT "(24/13)\n");
236*f5bf0ee4SLinus Walleij 		break;
237*f5bf0ee4SLinus Walleij 	case CPU_AHB_2_1:
238*f5bf0ee4SLinus Walleij 		printk(KERN_CONT "(2/1)\n");
239*f5bf0ee4SLinus Walleij 		break;
240*f5bf0ee4SLinus Walleij 	}
241*f5bf0ee4SLinus Walleij 
242*f5bf0ee4SLinus Walleij 	/*
243*f5bf0ee4SLinus Walleij 	 * Reset the interrupt mask and status
244*f5bf0ee4SLinus Walleij 	 */
245*f5bf0ee4SLinus Walleij 	writel(TIMER_INT_ALL_MASK, base + TIMER_INTR_MASK);
246*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER_INTR_STATE);
247*f5bf0ee4SLinus Walleij 	writel(TIMER_DEFAULT_FLAGS, base + TIMER_CR);
248*f5bf0ee4SLinus Walleij 
249*f5bf0ee4SLinus Walleij 	/*
250*f5bf0ee4SLinus Walleij 	 * Setup free-running clocksource timer (interrupts
251*f5bf0ee4SLinus Walleij 	 * disabled.)
252*f5bf0ee4SLinus Walleij 	 */
253*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER3_COUNT);
254*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER3_LOAD);
255*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER3_MATCH1);
256*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER3_MATCH2);
257*f5bf0ee4SLinus Walleij 	clocksource_mmio_init(base + TIMER3_COUNT,
258*f5bf0ee4SLinus Walleij 			      "fttmr010_clocksource", tick_rate,
259*f5bf0ee4SLinus Walleij 			      300, 32, clocksource_mmio_readl_up);
260*f5bf0ee4SLinus Walleij 	sched_clock_register(fttmr010_read_sched_clock, 32, tick_rate);
261*f5bf0ee4SLinus Walleij 
262*f5bf0ee4SLinus Walleij 	/*
263*f5bf0ee4SLinus Walleij 	 * Setup clockevent timer (interrupt-driven.)
264*f5bf0ee4SLinus Walleij 	 */
265*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER1_COUNT);
266*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER1_LOAD);
267*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER1_MATCH1);
268*f5bf0ee4SLinus Walleij 	writel(0, base + TIMER1_MATCH2);
269*f5bf0ee4SLinus Walleij 	setup_irq(irq, &fttmr010_timer_irq);
270*f5bf0ee4SLinus Walleij 	fttmr010_clockevent.cpumask = cpumask_of(0);
271*f5bf0ee4SLinus Walleij 	clockevents_config_and_register(&fttmr010_clockevent, tick_rate,
272*f5bf0ee4SLinus Walleij 					1, 0xffffffff);
273*f5bf0ee4SLinus Walleij 
274*f5bf0ee4SLinus Walleij 	return 0;
275*f5bf0ee4SLinus Walleij }
276*f5bf0ee4SLinus Walleij CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", gemini_timer_of_init);
277