1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Keystone broadcast clock-event
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2013 Texas Instruments, Inc.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/clk.h>
11*4882a593Smuzhiyun #include <linux/clockchips.h>
12*4882a593Smuzhiyun #include <linux/clocksource.h>
13*4882a593Smuzhiyun #include <linux/interrupt.h>
14*4882a593Smuzhiyun #include <linux/of_address.h>
15*4882a593Smuzhiyun #include <linux/of_irq.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define TIMER_NAME "timer-keystone"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /* Timer register offsets */
20*4882a593Smuzhiyun #define TIM12 0x10
21*4882a593Smuzhiyun #define TIM34 0x14
22*4882a593Smuzhiyun #define PRD12 0x18
23*4882a593Smuzhiyun #define PRD34 0x1c
24*4882a593Smuzhiyun #define TCR 0x20
25*4882a593Smuzhiyun #define TGCR 0x24
26*4882a593Smuzhiyun #define INTCTLSTAT 0x44
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /* Timer register bitfields */
29*4882a593Smuzhiyun #define TCR_ENAMODE_MASK 0xC0
30*4882a593Smuzhiyun #define TCR_ENAMODE_ONESHOT_MASK 0x40
31*4882a593Smuzhiyun #define TCR_ENAMODE_PERIODIC_MASK 0x80
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define TGCR_TIM_UNRESET_MASK 0x03
34*4882a593Smuzhiyun #define INTCTLSTAT_ENINT_MASK 0x01
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /**
37*4882a593Smuzhiyun * struct keystone_timer: holds timer's data
38*4882a593Smuzhiyun * @base: timer memory base address
39*4882a593Smuzhiyun * @hz_period: cycles per HZ period
40*4882a593Smuzhiyun * @event_dev: event device based on timer
41*4882a593Smuzhiyun */
42*4882a593Smuzhiyun static struct keystone_timer {
43*4882a593Smuzhiyun void __iomem *base;
44*4882a593Smuzhiyun unsigned long hz_period;
45*4882a593Smuzhiyun struct clock_event_device event_dev;
46*4882a593Smuzhiyun } timer;
47*4882a593Smuzhiyun
keystone_timer_readl(unsigned long rg)48*4882a593Smuzhiyun static inline u32 keystone_timer_readl(unsigned long rg)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun return readl_relaxed(timer.base + rg);
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun
keystone_timer_writel(u32 val,unsigned long rg)53*4882a593Smuzhiyun static inline void keystone_timer_writel(u32 val, unsigned long rg)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun writel_relaxed(val, timer.base + rg);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /**
59*4882a593Smuzhiyun * keystone_timer_barrier: write memory barrier
60*4882a593Smuzhiyun * use explicit barrier to avoid using readl/writel non relaxed function
61*4882a593Smuzhiyun * variants, because in our case non relaxed variants hide the true places
62*4882a593Smuzhiyun * where barrier is needed.
63*4882a593Smuzhiyun */
keystone_timer_barrier(void)64*4882a593Smuzhiyun static inline void keystone_timer_barrier(void)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun __iowmb();
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /**
70*4882a593Smuzhiyun * keystone_timer_config: configures timer to work in oneshot/periodic modes.
71*4882a593Smuzhiyun * @ mask: mask of the mode to configure
72*4882a593Smuzhiyun * @ period: cycles number to configure for
73*4882a593Smuzhiyun */
keystone_timer_config(u64 period,int mask)74*4882a593Smuzhiyun static int keystone_timer_config(u64 period, int mask)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun u32 tcr;
77*4882a593Smuzhiyun u32 off;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun tcr = keystone_timer_readl(TCR);
80*4882a593Smuzhiyun off = tcr & ~(TCR_ENAMODE_MASK);
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /* set enable mode */
83*4882a593Smuzhiyun tcr |= mask;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /* disable timer */
86*4882a593Smuzhiyun keystone_timer_writel(off, TCR);
87*4882a593Smuzhiyun /* here we have to be sure the timer has been disabled */
88*4882a593Smuzhiyun keystone_timer_barrier();
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* reset counter to zero, set new period */
91*4882a593Smuzhiyun keystone_timer_writel(0, TIM12);
92*4882a593Smuzhiyun keystone_timer_writel(0, TIM34);
93*4882a593Smuzhiyun keystone_timer_writel(period & 0xffffffff, PRD12);
94*4882a593Smuzhiyun keystone_timer_writel(period >> 32, PRD34);
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun /*
97*4882a593Smuzhiyun * enable timer
98*4882a593Smuzhiyun * here we have to be sure that CNTLO, CNTHI, PRDLO, PRDHI registers
99*4882a593Smuzhiyun * have been written.
100*4882a593Smuzhiyun */
101*4882a593Smuzhiyun keystone_timer_barrier();
102*4882a593Smuzhiyun keystone_timer_writel(tcr, TCR);
103*4882a593Smuzhiyun return 0;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
keystone_timer_disable(void)106*4882a593Smuzhiyun static void keystone_timer_disable(void)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun u32 tcr;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun tcr = keystone_timer_readl(TCR);
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /* disable timer */
113*4882a593Smuzhiyun tcr &= ~(TCR_ENAMODE_MASK);
114*4882a593Smuzhiyun keystone_timer_writel(tcr, TCR);
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
keystone_timer_interrupt(int irq,void * dev_id)117*4882a593Smuzhiyun static irqreturn_t keystone_timer_interrupt(int irq, void *dev_id)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun struct clock_event_device *evt = dev_id;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun evt->event_handler(evt);
122*4882a593Smuzhiyun return IRQ_HANDLED;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
keystone_set_next_event(unsigned long cycles,struct clock_event_device * evt)125*4882a593Smuzhiyun static int keystone_set_next_event(unsigned long cycles,
126*4882a593Smuzhiyun struct clock_event_device *evt)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun return keystone_timer_config(cycles, TCR_ENAMODE_ONESHOT_MASK);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
keystone_shutdown(struct clock_event_device * evt)131*4882a593Smuzhiyun static int keystone_shutdown(struct clock_event_device *evt)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun keystone_timer_disable();
134*4882a593Smuzhiyun return 0;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
keystone_set_periodic(struct clock_event_device * evt)137*4882a593Smuzhiyun static int keystone_set_periodic(struct clock_event_device *evt)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun keystone_timer_config(timer.hz_period, TCR_ENAMODE_PERIODIC_MASK);
140*4882a593Smuzhiyun return 0;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
keystone_timer_init(struct device_node * np)143*4882a593Smuzhiyun static int __init keystone_timer_init(struct device_node *np)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun struct clock_event_device *event_dev = &timer.event_dev;
146*4882a593Smuzhiyun unsigned long rate;
147*4882a593Smuzhiyun struct clk *clk;
148*4882a593Smuzhiyun int irq, error;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun irq = irq_of_parse_and_map(np, 0);
151*4882a593Smuzhiyun if (!irq) {
152*4882a593Smuzhiyun pr_err("%s: failed to map interrupts\n", __func__);
153*4882a593Smuzhiyun return -EINVAL;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun timer.base = of_iomap(np, 0);
157*4882a593Smuzhiyun if (!timer.base) {
158*4882a593Smuzhiyun pr_err("%s: failed to map registers\n", __func__);
159*4882a593Smuzhiyun return -ENXIO;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun clk = of_clk_get(np, 0);
163*4882a593Smuzhiyun if (IS_ERR(clk)) {
164*4882a593Smuzhiyun pr_err("%s: failed to get clock\n", __func__);
165*4882a593Smuzhiyun iounmap(timer.base);
166*4882a593Smuzhiyun return PTR_ERR(clk);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun error = clk_prepare_enable(clk);
170*4882a593Smuzhiyun if (error) {
171*4882a593Smuzhiyun pr_err("%s: failed to enable clock\n", __func__);
172*4882a593Smuzhiyun goto err;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun rate = clk_get_rate(clk);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /* disable, use internal clock source */
178*4882a593Smuzhiyun keystone_timer_writel(0, TCR);
179*4882a593Smuzhiyun /* here we have to be sure the timer has been disabled */
180*4882a593Smuzhiyun keystone_timer_barrier();
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* reset timer as 64-bit, no pre-scaler, plus features are disabled */
183*4882a593Smuzhiyun keystone_timer_writel(0, TGCR);
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /* unreset timer */
186*4882a593Smuzhiyun keystone_timer_writel(TGCR_TIM_UNRESET_MASK, TGCR);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /* init counter to zero */
189*4882a593Smuzhiyun keystone_timer_writel(0, TIM12);
190*4882a593Smuzhiyun keystone_timer_writel(0, TIM34);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun timer.hz_period = DIV_ROUND_UP(rate, HZ);
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /* enable timer interrupts */
195*4882a593Smuzhiyun keystone_timer_writel(INTCTLSTAT_ENINT_MASK, INTCTLSTAT);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun error = request_irq(irq, keystone_timer_interrupt, IRQF_TIMER,
198*4882a593Smuzhiyun TIMER_NAME, event_dev);
199*4882a593Smuzhiyun if (error) {
200*4882a593Smuzhiyun pr_err("%s: failed to setup irq\n", __func__);
201*4882a593Smuzhiyun goto err;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /* setup clockevent */
205*4882a593Smuzhiyun event_dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
206*4882a593Smuzhiyun event_dev->set_next_event = keystone_set_next_event;
207*4882a593Smuzhiyun event_dev->set_state_shutdown = keystone_shutdown;
208*4882a593Smuzhiyun event_dev->set_state_periodic = keystone_set_periodic;
209*4882a593Smuzhiyun event_dev->set_state_oneshot = keystone_shutdown;
210*4882a593Smuzhiyun event_dev->cpumask = cpu_possible_mask;
211*4882a593Smuzhiyun event_dev->owner = THIS_MODULE;
212*4882a593Smuzhiyun event_dev->name = TIMER_NAME;
213*4882a593Smuzhiyun event_dev->irq = irq;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun clockevents_config_and_register(event_dev, rate, 1, ULONG_MAX);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun pr_info("keystone timer clock @%lu Hz\n", rate);
218*4882a593Smuzhiyun return 0;
219*4882a593Smuzhiyun err:
220*4882a593Smuzhiyun clk_put(clk);
221*4882a593Smuzhiyun iounmap(timer.base);
222*4882a593Smuzhiyun return error;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun TIMER_OF_DECLARE(keystone_timer, "ti,keystone-timer",
226*4882a593Smuzhiyun keystone_timer_init);
227