1 // SPDX-License-Identifier: GPL-2.0-only
3 * Keystone broadcast clock-event
5 * Copyright 2013 Texas Instruments, Inc.
7 * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
10 #include <linux/clk.h>
11 #include <linux/clockchips.h>
12 #include <linux/clocksource.h>
13 #include <linux/interrupt.h>
14 #include <linux/of_address.h>
15 #include <linux/of_irq.h>
17 #define TIMER_NAME "timer-keystone"
19 /* Timer register offsets */
26 #define INTCTLSTAT 0x44
28 /* Timer register bitfields */
29 #define TCR_ENAMODE_MASK 0xC0
30 #define TCR_ENAMODE_ONESHOT_MASK 0x40
31 #define TCR_ENAMODE_PERIODIC_MASK 0x80
33 #define TGCR_TIM_UNRESET_MASK 0x03
34 #define INTCTLSTAT_ENINT_MASK 0x01
37 * struct keystone_timer: holds timer's data
38 * @base: timer memory base address
39 * @hz_period: cycles per HZ period
40 * @event_dev: event device based on timer
42 static struct keystone_timer
{
44 unsigned long hz_period
;
45 struct clock_event_device event_dev
;
48 static inline u32
keystone_timer_readl(unsigned long rg
)
50 return readl_relaxed(timer
.base
+ rg
);
53 static inline void keystone_timer_writel(u32 val
, unsigned long rg
)
55 writel_relaxed(val
, timer
.base
+ rg
);
59 * keystone_timer_barrier: write memory barrier
60 * use explicit barrier to avoid using readl/writel non relaxed function
61 * variants, because in our case non relaxed variants hide the true places
62 * where barrier is needed.
64 static inline void keystone_timer_barrier(void)
70 * keystone_timer_config: configures timer to work in oneshot/periodic modes.
71 * @ mask: mask of the mode to configure
72 * @ period: cycles number to configure for
74 static int keystone_timer_config(u64 period
, int mask
)
79 tcr
= keystone_timer_readl(TCR
);
80 off
= tcr
& ~(TCR_ENAMODE_MASK
);
86 keystone_timer_writel(off
, TCR
);
87 /* here we have to be sure the timer has been disabled */
88 keystone_timer_barrier();
90 /* reset counter to zero, set new period */
91 keystone_timer_writel(0, TIM12
);
92 keystone_timer_writel(0, TIM34
);
93 keystone_timer_writel(period
& 0xffffffff, PRD12
);
94 keystone_timer_writel(period
>> 32, PRD34
);
98 * here we have to be sure that CNTLO, CNTHI, PRDLO, PRDHI registers
101 keystone_timer_barrier();
102 keystone_timer_writel(tcr
, TCR
);
106 static void keystone_timer_disable(void)
110 tcr
= keystone_timer_readl(TCR
);
113 tcr
&= ~(TCR_ENAMODE_MASK
);
114 keystone_timer_writel(tcr
, TCR
);
117 static irqreturn_t
keystone_timer_interrupt(int irq
, void *dev_id
)
119 struct clock_event_device
*evt
= dev_id
;
121 evt
->event_handler(evt
);
125 static int keystone_set_next_event(unsigned long cycles
,
126 struct clock_event_device
*evt
)
128 return keystone_timer_config(cycles
, TCR_ENAMODE_ONESHOT_MASK
);
131 static int keystone_shutdown(struct clock_event_device
*evt
)
133 keystone_timer_disable();
137 static int keystone_set_periodic(struct clock_event_device
*evt
)
139 keystone_timer_config(timer
.hz_period
, TCR_ENAMODE_PERIODIC_MASK
);
143 static int __init
keystone_timer_init(struct device_node
*np
)
145 struct clock_event_device
*event_dev
= &timer
.event_dev
;
150 irq
= irq_of_parse_and_map(np
, 0);
152 pr_err("%s: failed to map interrupts\n", __func__
);
156 timer
.base
= of_iomap(np
, 0);
158 pr_err("%s: failed to map registers\n", __func__
);
162 clk
= of_clk_get(np
, 0);
164 pr_err("%s: failed to get clock\n", __func__
);
169 error
= clk_prepare_enable(clk
);
171 pr_err("%s: failed to enable clock\n", __func__
);
175 rate
= clk_get_rate(clk
);
177 /* disable, use internal clock source */
178 keystone_timer_writel(0, TCR
);
179 /* here we have to be sure the timer has been disabled */
180 keystone_timer_barrier();
182 /* reset timer as 64-bit, no pre-scaler, plus features are disabled */
183 keystone_timer_writel(0, TGCR
);
186 keystone_timer_writel(TGCR_TIM_UNRESET_MASK
, TGCR
);
188 /* init counter to zero */
189 keystone_timer_writel(0, TIM12
);
190 keystone_timer_writel(0, TIM34
);
192 timer
.hz_period
= DIV_ROUND_UP(rate
, HZ
);
194 /* enable timer interrupts */
195 keystone_timer_writel(INTCTLSTAT_ENINT_MASK
, INTCTLSTAT
);
197 error
= request_irq(irq
, keystone_timer_interrupt
, IRQF_TIMER
,
198 TIMER_NAME
, event_dev
);
200 pr_err("%s: failed to setup irq\n", __func__
);
204 /* setup clockevent */
205 event_dev
->features
= CLOCK_EVT_FEAT_PERIODIC
| CLOCK_EVT_FEAT_ONESHOT
;
206 event_dev
->set_next_event
= keystone_set_next_event
;
207 event_dev
->set_state_shutdown
= keystone_shutdown
;
208 event_dev
->set_state_periodic
= keystone_set_periodic
;
209 event_dev
->set_state_oneshot
= keystone_shutdown
;
210 event_dev
->cpumask
= cpu_possible_mask
;
211 event_dev
->owner
= THIS_MODULE
;
212 event_dev
->name
= TIMER_NAME
;
213 event_dev
->irq
= irq
;
215 clockevents_config_and_register(event_dev
, rate
, 1, ULONG_MAX
);
217 pr_info("keystone timer clock @%lu Hz\n", rate
);
225 TIMER_OF_DECLARE(keystone_timer
, "ti,keystone-timer",
226 keystone_timer_init
);