2 * Keystone broadcast clock-event
4 * Copyright 2013 Texas Instruments, Inc.
6 * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 #include <linux/clk.h>
15 #include <linux/clockchips.h>
16 #include <linux/clocksource.h>
17 #include <linux/interrupt.h>
18 #include <linux/of_address.h>
19 #include <linux/of_irq.h>
21 #define TIMER_NAME "timer-keystone"
23 /* Timer register offsets */
30 #define INTCTLSTAT 0x44
32 /* Timer register bitfields */
33 #define TCR_ENAMODE_MASK 0xC0
34 #define TCR_ENAMODE_ONESHOT_MASK 0x40
35 #define TCR_ENAMODE_PERIODIC_MASK 0x80
37 #define TGCR_TIM_UNRESET_MASK 0x03
38 #define INTCTLSTAT_ENINT_MASK 0x01
41 * struct keystone_timer: holds timer's data
42 * @base: timer memory base address
43 * @hz_period: cycles per HZ period
44 * @event_dev: event device based on timer
46 static struct keystone_timer
{
48 unsigned long hz_period
;
49 struct clock_event_device event_dev
;
52 static inline u32
keystone_timer_readl(unsigned long rg
)
54 return readl_relaxed(timer
.base
+ rg
);
57 static inline void keystone_timer_writel(u32 val
, unsigned long rg
)
59 writel_relaxed(val
, timer
.base
+ rg
);
63 * keystone_timer_barrier: write memory barrier
64 * use explicit barrier to avoid using readl/writel non relaxed function
65 * variants, because in our case non relaxed variants hide the true places
66 * where barrier is needed.
68 static inline void keystone_timer_barrier(void)
74 * keystone_timer_config: configures timer to work in oneshot/periodic modes.
75 * @ mask: mask of the mode to configure
76 * @ period: cycles number to configure for
78 static int keystone_timer_config(u64 period
, int mask
)
83 tcr
= keystone_timer_readl(TCR
);
84 off
= tcr
& ~(TCR_ENAMODE_MASK
);
90 keystone_timer_writel(off
, TCR
);
91 /* here we have to be sure the timer has been disabled */
92 keystone_timer_barrier();
94 /* reset counter to zero, set new period */
95 keystone_timer_writel(0, TIM12
);
96 keystone_timer_writel(0, TIM34
);
97 keystone_timer_writel(period
& 0xffffffff, PRD12
);
98 keystone_timer_writel(period
>> 32, PRD34
);
102 * here we have to be sure that CNTLO, CNTHI, PRDLO, PRDHI registers
105 keystone_timer_barrier();
106 keystone_timer_writel(tcr
, TCR
);
110 static void keystone_timer_disable(void)
114 tcr
= keystone_timer_readl(TCR
);
117 tcr
&= ~(TCR_ENAMODE_MASK
);
118 keystone_timer_writel(tcr
, TCR
);
121 static irqreturn_t
keystone_timer_interrupt(int irq
, void *dev_id
)
123 struct clock_event_device
*evt
= dev_id
;
125 evt
->event_handler(evt
);
129 static int keystone_set_next_event(unsigned long cycles
,
130 struct clock_event_device
*evt
)
132 return keystone_timer_config(cycles
, TCR_ENAMODE_ONESHOT_MASK
);
135 static int keystone_shutdown(struct clock_event_device
*evt
)
137 keystone_timer_disable();
141 static int keystone_set_periodic(struct clock_event_device
*evt
)
143 keystone_timer_config(timer
.hz_period
, TCR_ENAMODE_PERIODIC_MASK
);
147 static int __init
keystone_timer_init(struct device_node
*np
)
149 struct clock_event_device
*event_dev
= &timer
.event_dev
;
154 irq
= irq_of_parse_and_map(np
, 0);
156 pr_err("%s: failed to map interrupts\n", __func__
);
160 timer
.base
= of_iomap(np
, 0);
162 pr_err("%s: failed to map registers\n", __func__
);
166 clk
= of_clk_get(np
, 0);
168 pr_err("%s: failed to get clock\n", __func__
);
173 error
= clk_prepare_enable(clk
);
175 pr_err("%s: failed to enable clock\n", __func__
);
179 rate
= clk_get_rate(clk
);
181 /* disable, use internal clock source */
182 keystone_timer_writel(0, TCR
);
183 /* here we have to be sure the timer has been disabled */
184 keystone_timer_barrier();
186 /* reset timer as 64-bit, no pre-scaler, plus features are disabled */
187 keystone_timer_writel(0, TGCR
);
190 keystone_timer_writel(TGCR_TIM_UNRESET_MASK
, TGCR
);
192 /* init counter to zero */
193 keystone_timer_writel(0, TIM12
);
194 keystone_timer_writel(0, TIM34
);
196 timer
.hz_period
= DIV_ROUND_UP(rate
, HZ
);
198 /* enable timer interrupts */
199 keystone_timer_writel(INTCTLSTAT_ENINT_MASK
, INTCTLSTAT
);
201 error
= request_irq(irq
, keystone_timer_interrupt
, IRQF_TIMER
,
202 TIMER_NAME
, event_dev
);
204 pr_err("%s: failed to setup irq\n", __func__
);
208 /* setup clockevent */
209 event_dev
->features
= CLOCK_EVT_FEAT_PERIODIC
| CLOCK_EVT_FEAT_ONESHOT
;
210 event_dev
->set_next_event
= keystone_set_next_event
;
211 event_dev
->set_state_shutdown
= keystone_shutdown
;
212 event_dev
->set_state_periodic
= keystone_set_periodic
;
213 event_dev
->set_state_oneshot
= keystone_shutdown
;
214 event_dev
->cpumask
= cpu_all_mask
;
215 event_dev
->owner
= THIS_MODULE
;
216 event_dev
->name
= TIMER_NAME
;
217 event_dev
->irq
= irq
;
219 clockevents_config_and_register(event_dev
, rate
, 1, ULONG_MAX
);
221 pr_info("keystone timer clock @%lu Hz\n", rate
);
229 CLOCKSOURCE_OF_DECLARE(keystone_timer
, "ti,keystone-timer",
230 keystone_timer_init
);