2 * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
3 * Copyright (C) 2012-2013 Xilinx, Inc.
4 * Copyright (C) 2007-2009 PetaLogix
5 * Copyright (C) 2006 Atmark Techno, Inc.
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
12 #include <linux/interrupt.h>
13 #include <linux/delay.h>
14 #include <linux/sched.h>
15 #include <linux/clk.h>
16 #include <linux/clockchips.h>
17 #include <linux/of_address.h>
18 #include <asm/cpuinfo.h>
19 #include <linux/cnt32_to_63.h>
21 static void __iomem
*timer_baseaddr
;
23 static unsigned int freq_div_hz
;
24 static unsigned int timer_clock_freq
;
33 #define TCSR_MDT (1<<0)
34 #define TCSR_UDT (1<<1)
35 #define TCSR_GENT (1<<2)
36 #define TCSR_CAPT (1<<3)
37 #define TCSR_ARHT (1<<4)
38 #define TCSR_LOAD (1<<5)
39 #define TCSR_ENIT (1<<6)
40 #define TCSR_ENT (1<<7)
41 #define TCSR_TINT (1<<8)
42 #define TCSR_PWMA (1<<9)
43 #define TCSR_ENALL (1<<10)
45 static inline void xilinx_timer0_stop(void)
47 out_be32(timer_baseaddr
+ TCSR0
,
48 in_be32(timer_baseaddr
+ TCSR0
) & ~TCSR_ENT
);
51 static inline void xilinx_timer0_start_periodic(unsigned long load_val
)
55 /* loading value to timer reg */
56 out_be32(timer_baseaddr
+ TLR0
, load_val
);
58 /* load the initial value */
59 out_be32(timer_baseaddr
+ TCSR0
, TCSR_LOAD
);
61 /* see timer data sheet for detail
62 * !ENALL - don't enable 'em all
64 * TINT - clear interrupt status
65 * ENT- enable timer itself
66 * ENIT - enable interrupt
67 * !LOAD - clear the bit to let go
69 * !CAPT - no external trigger
70 * !GENT - no external signal
71 * UDT - set the timer as down counter
72 * !MDT0 - generate mode
74 out_be32(timer_baseaddr
+ TCSR0
,
75 TCSR_TINT
|TCSR_ENIT
|TCSR_ENT
|TCSR_ARHT
|TCSR_UDT
);
78 static inline void xilinx_timer0_start_oneshot(unsigned long load_val
)
82 /* loading value to timer reg */
83 out_be32(timer_baseaddr
+ TLR0
, load_val
);
85 /* load the initial value */
86 out_be32(timer_baseaddr
+ TCSR0
, TCSR_LOAD
);
88 out_be32(timer_baseaddr
+ TCSR0
,
89 TCSR_TINT
|TCSR_ENIT
|TCSR_ENT
|TCSR_ARHT
|TCSR_UDT
);
92 static int xilinx_timer_set_next_event(unsigned long delta
,
93 struct clock_event_device
*dev
)
95 pr_debug("%s: next event, delta %x\n", __func__
, (u32
)delta
);
96 xilinx_timer0_start_oneshot(delta
);
100 static void xilinx_timer_set_mode(enum clock_event_mode mode
,
101 struct clock_event_device
*evt
)
104 case CLOCK_EVT_MODE_PERIODIC
:
105 pr_info("%s: periodic\n", __func__
);
106 xilinx_timer0_start_periodic(freq_div_hz
);
108 case CLOCK_EVT_MODE_ONESHOT
:
109 pr_info("%s: oneshot\n", __func__
);
111 case CLOCK_EVT_MODE_UNUSED
:
112 pr_info("%s: unused\n", __func__
);
114 case CLOCK_EVT_MODE_SHUTDOWN
:
115 pr_info("%s: shutdown\n", __func__
);
116 xilinx_timer0_stop();
118 case CLOCK_EVT_MODE_RESUME
:
119 pr_info("%s: resume\n", __func__
);
124 static struct clock_event_device clockevent_xilinx_timer
= {
125 .name
= "xilinx_clockevent",
126 .features
= CLOCK_EVT_FEAT_ONESHOT
| CLOCK_EVT_FEAT_PERIODIC
,
129 .set_next_event
= xilinx_timer_set_next_event
,
130 .set_mode
= xilinx_timer_set_mode
,
133 static inline void timer_ack(void)
135 out_be32(timer_baseaddr
+ TCSR0
, in_be32(timer_baseaddr
+ TCSR0
));
138 static irqreturn_t
timer_interrupt(int irq
, void *dev_id
)
140 struct clock_event_device
*evt
= &clockevent_xilinx_timer
;
141 #ifdef CONFIG_HEART_BEAT
145 evt
->event_handler(evt
);
149 static struct irqaction timer_irqaction
= {
150 .handler
= timer_interrupt
,
151 .flags
= IRQF_DISABLED
| IRQF_TIMER
,
153 .dev_id
= &clockevent_xilinx_timer
,
156 static __init
void xilinx_clockevent_init(void)
158 clockevent_xilinx_timer
.mult
=
159 div_sc(timer_clock_freq
, NSEC_PER_SEC
,
160 clockevent_xilinx_timer
.shift
);
161 clockevent_xilinx_timer
.max_delta_ns
=
162 clockevent_delta2ns((u32
)~0, &clockevent_xilinx_timer
);
163 clockevent_xilinx_timer
.min_delta_ns
=
164 clockevent_delta2ns(1, &clockevent_xilinx_timer
);
165 clockevent_xilinx_timer
.cpumask
= cpumask_of(0);
166 clockevents_register_device(&clockevent_xilinx_timer
);
169 static cycle_t
xilinx_read(struct clocksource
*cs
)
171 /* reading actual value of timer 1 */
172 return (cycle_t
) (in_be32(timer_baseaddr
+ TCR1
));
175 static struct timecounter xilinx_tc
= {
179 static cycle_t
xilinx_cc_read(const struct cyclecounter
*cc
)
181 return xilinx_read(NULL
);
184 static struct cyclecounter xilinx_cc
= {
185 .read
= xilinx_cc_read
,
186 .mask
= CLOCKSOURCE_MASK(32),
190 static int __init
init_xilinx_timecounter(void)
192 xilinx_cc
.mult
= div_sc(timer_clock_freq
, NSEC_PER_SEC
,
195 timecounter_init(&xilinx_tc
, &xilinx_cc
, sched_clock());
200 static struct clocksource clocksource_microblaze
= {
201 .name
= "xilinx_clocksource",
204 .mask
= CLOCKSOURCE_MASK(32),
205 .flags
= CLOCK_SOURCE_IS_CONTINUOUS
,
208 static int __init
xilinx_clocksource_init(void)
210 if (clocksource_register_hz(&clocksource_microblaze
, timer_clock_freq
))
211 panic("failed to register clocksource");
214 out_be32(timer_baseaddr
+ TCSR1
,
215 in_be32(timer_baseaddr
+ TCSR1
) & ~TCSR_ENT
);
216 /* start timer1 - up counting without interrupt */
217 out_be32(timer_baseaddr
+ TCSR1
, TCSR_TINT
|TCSR_ENT
|TCSR_ARHT
);
219 /* register timecounter - for ftrace support */
220 init_xilinx_timecounter();
225 * We have to protect accesses before timer initialization
226 * and return 0 for sched_clock function below.
228 static int timer_initialized
;
230 static void __init
xilinx_timer_init(struct device_node
*timer
)
236 timer_baseaddr
= of_iomap(timer
, 0);
237 if (!timer_baseaddr
) {
238 pr_err("ERROR: invalid timer base address\n");
242 irq
= irq_of_parse_and_map(timer
, 0);
244 of_property_read_u32(timer
, "xlnx,one-timer-only", &timer_num
);
246 pr_emerg("Please enable two timers in HW\n");
250 pr_info("%s: irq=%d\n", timer
->full_name
, irq
);
252 /* If there is clock-frequency property than use it */
253 ret
= of_property_read_u32(timer
, "clock-frequency", &timer_clock_freq
);
255 timer_clock_freq
= cpuinfo
.cpu_clock_freq
;
257 freq_div_hz
= timer_clock_freq
/ HZ
;
259 setup_irq(irq
, &timer_irqaction
);
260 #ifdef CONFIG_HEART_BEAT
263 xilinx_clocksource_init();
264 xilinx_clockevent_init();
265 timer_initialized
= 1;
268 unsigned long long notrace
sched_clock(void)
270 if (timer_initialized
) {
271 struct clocksource
*cs
= &clocksource_microblaze
;
273 cycle_t cyc
= cnt32_to_63(cs
->read(NULL
)) & LLONG_MAX
;
274 return clocksource_cyc2ns(cyc
, cs
->mult
, cs
->shift
);
279 CLOCKSOURCE_OF_DECLARE(xilinx_timer
, "xlnx,xps-timer-1.00.a",