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 * @ mode: mode to configure
76 * @ period: cycles number to configure for
78 static int keystone_timer_config(u64 period
, enum clock_event_mode mode
)
83 tcr
= keystone_timer_readl(TCR
);
84 off
= tcr
& ~(TCR_ENAMODE_MASK
);
88 case CLOCK_EVT_MODE_ONESHOT
:
89 tcr
|= TCR_ENAMODE_ONESHOT_MASK
;
91 case CLOCK_EVT_MODE_PERIODIC
:
92 tcr
|= TCR_ENAMODE_PERIODIC_MASK
;
99 keystone_timer_writel(off
, TCR
);
100 /* here we have to be sure the timer has been disabled */
101 keystone_timer_barrier();
103 /* reset counter to zero, set new period */
104 keystone_timer_writel(0, TIM12
);
105 keystone_timer_writel(0, TIM34
);
106 keystone_timer_writel(period
& 0xffffffff, PRD12
);
107 keystone_timer_writel(period
>> 32, PRD34
);
111 * here we have to be sure that CNTLO, CNTHI, PRDLO, PRDHI registers
114 keystone_timer_barrier();
115 keystone_timer_writel(tcr
, TCR
);
119 static void keystone_timer_disable(void)
123 tcr
= keystone_timer_readl(TCR
);
126 tcr
&= ~(TCR_ENAMODE_MASK
);
127 keystone_timer_writel(tcr
, TCR
);
130 static irqreturn_t
keystone_timer_interrupt(int irq
, void *dev_id
)
132 struct clock_event_device
*evt
= dev_id
;
134 evt
->event_handler(evt
);
138 static int keystone_set_next_event(unsigned long cycles
,
139 struct clock_event_device
*evt
)
141 return keystone_timer_config(cycles
, evt
->mode
);
144 static void keystone_set_mode(enum clock_event_mode mode
,
145 struct clock_event_device
*evt
)
148 case CLOCK_EVT_MODE_PERIODIC
:
149 keystone_timer_config(timer
.hz_period
, CLOCK_EVT_MODE_PERIODIC
);
151 case CLOCK_EVT_MODE_UNUSED
:
152 case CLOCK_EVT_MODE_SHUTDOWN
:
153 case CLOCK_EVT_MODE_ONESHOT
:
154 keystone_timer_disable();
161 static void __init
keystone_timer_init(struct device_node
*np
)
163 struct clock_event_device
*event_dev
= &timer
.event_dev
;
168 irq
= irq_of_parse_and_map(np
, 0);
170 pr_err("%s: failed to map interrupts\n", __func__
);
174 timer
.base
= of_iomap(np
, 0);
176 pr_err("%s: failed to map registers\n", __func__
);
180 clk
= of_clk_get(np
, 0);
182 pr_err("%s: failed to get clock\n", __func__
);
187 error
= clk_prepare_enable(clk
);
189 pr_err("%s: failed to enable clock\n", __func__
);
193 rate
= clk_get_rate(clk
);
195 /* disable, use internal clock source */
196 keystone_timer_writel(0, TCR
);
197 /* here we have to be sure the timer has been disabled */
198 keystone_timer_barrier();
200 /* reset timer as 64-bit, no pre-scaler, plus features are disabled */
201 keystone_timer_writel(0, TGCR
);
204 keystone_timer_writel(TGCR_TIM_UNRESET_MASK
, TGCR
);
206 /* init counter to zero */
207 keystone_timer_writel(0, TIM12
);
208 keystone_timer_writel(0, TIM34
);
210 timer
.hz_period
= DIV_ROUND_UP(rate
, HZ
);
212 /* enable timer interrupts */
213 keystone_timer_writel(INTCTLSTAT_ENINT_MASK
, INTCTLSTAT
);
215 error
= request_irq(irq
, keystone_timer_interrupt
, IRQF_TIMER
,
216 TIMER_NAME
, event_dev
);
218 pr_err("%s: failed to setup irq\n", __func__
);
222 /* setup clockevent */
223 event_dev
->features
= CLOCK_EVT_FEAT_PERIODIC
| CLOCK_EVT_FEAT_ONESHOT
;
224 event_dev
->set_next_event
= keystone_set_next_event
;
225 event_dev
->set_mode
= keystone_set_mode
;
226 event_dev
->cpumask
= cpu_all_mask
;
227 event_dev
->owner
= THIS_MODULE
;
228 event_dev
->name
= TIMER_NAME
;
229 event_dev
->irq
= irq
;
231 clockevents_config_and_register(event_dev
, rate
, 1, ULONG_MAX
);
233 pr_info("keystone timer clock @%lu Hz\n", rate
);
240 CLOCKSOURCE_OF_DECLARE(keystone_timer
, "ti,keystone-timer",
241 keystone_timer_init
);