1 /* $NetBSD: omap2430_mputmr.c,v 1.3 2008/07/03 06:19:18 matt Exp $ */
8 * Based on i80321_timer.c and arch/arm/sa11x0/sa11x0_ost.c
10 * Copyright (c) 1997 Mark Brinicombe.
11 * Copyright (c) 1997 Causality Limited.
12 * All rights reserved.
14 * This code is derived from software contributed to The NetBSD Foundation
15 * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. All advertising materials mentioning features or use of this software
26 * must display the following acknowledgement:
27 * This product includes software developed by the NetBSD
28 * Foundation, Inc. and its contributors.
29 * 4. Neither the name of The NetBSD Foundation nor the names of its
30 * contributors may be used to endorse or promote products derived
31 * from this software without specific prior written permission.
33 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
34 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
35 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
36 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
37 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
39 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
40 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 * POSSIBILITY OF SUCH DAMAGE.
45 * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
46 * All rights reserved.
48 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
53 * 1. Redistributions of source code must retain the above copyright
54 * notice, this list of conditions and the following disclaimer.
55 * 2. Redistributions in binary form must reproduce the above copyright
56 * notice, this list of conditions and the following disclaimer in the
57 * documentation and/or other materials provided with the distribution.
58 * 3. All advertising materials mentioning features or use of this software
59 * must display the following acknowledgement:
60 * This product includes software developed for the NetBSD Project by
61 * Wasabi Systems, Inc.
62 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
63 * or promote products derived from this software without specific prior
66 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
67 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
68 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
69 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
70 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
71 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
72 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
73 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
74 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
75 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
76 * POSSIBILITY OF SUCH DAMAGE.
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: omap2430_mputmr.c,v 1.3 2008/07/03 06:19:18 matt Exp $");
83 #include "opt_cpuoptions.h"
85 #include <sys/types.h>
86 #include <sys/param.h>
87 #include <sys/systm.h>
88 #include <sys/kernel.h>
90 #include <sys/timetc.h>
91 #include <sys/device.h>
93 #include <dev/clock_subr.h>
95 #include <machine/bus.h>
96 #include <machine/intr.h>
98 #include <arm/omap/omap_gptmrreg.h>
99 #include <arm/omap/omap2_mputmrvar.h>
102 uint32_t counts_per_usec
, counts_per_hz
;
104 struct mputmr_softc
*clock_sc
;
105 struct mputmr_softc
*stat_sc
;
106 struct mputmr_softc
*ref_sc
;
107 static uint32_t mpu_get_timecount(struct timecounter
*);
109 static struct timecounter mpu_timecounter
= {
110 .tc_get_timecount
= mpu_get_timecount
,
111 .tc_counter_mask
= 0xffffffff,
112 .tc_frequency
= OMAP_MPU_TIMER_CLOCK_FREQ
,
119 _timer_intr_dis(struct mputmr_softc
*sc
)
121 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TIER
, 0);
125 _timer_intr_enb(struct mputmr_softc
*sc
)
127 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TIER
, TIER_OVF_IT_ENA
);
130 static inline uint32_t
131 _timer_intr_sts(struct mputmr_softc
*sc
)
133 return bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, TISR
);
137 _timer_intr_ack(struct mputmr_softc
*sc
)
139 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TISR
, TIER_OVF_IT_ENA
);
142 static inline uint32_t
143 _timer_read(struct mputmr_softc
*sc
)
145 return bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, TCRR
);
149 _timer_stop(struct mputmr_softc
*sc
)
153 r
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, TCLR
);
155 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TCLR
, r
);
159 _timer_reload(struct mputmr_softc
*sc
, uint32_t val
)
161 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TLDR
, val
);
162 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TCRR
, val
);
166 _timer_start(struct mputmr_softc
*sc
, timer_factors
*tfp
)
172 r
|= (TCLR_PTV(tfp
->ptv
- 1) & TCLR_PTV_MASK
);
174 r
|= (TCLR_CE
| TCLR_AR
| TCLR_ST
);
176 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TCLR
, r
);
180 mpu_get_timecount(struct timecounter
*tc
)
182 return _timer_read(ref_sc
);
186 clockintr(void *frame
)
188 _timer_intr_ack(clock_sc
);
194 statintr(void *frame
)
196 _timer_intr_ack(stat_sc
);
202 setclockrate(struct mputmr_softc
*sc
, int schz
)
207 calc_timer_factors(schz
, &tf
);
208 _timer_reload(sc
, tf
.reload
);
209 _timer_start(sc
, &tf
);
213 setstatclockrate(int schz
)
215 setclockrate(stat_sc
, schz
);
221 if (clock_sc
== NULL
)
222 panic("Clock timer was not configured.");
224 panic("Statistics timer was not configured.");
226 panic("Microtime reference timer was not configured.");
229 * We already have the timers running, but not generating interrupts.
230 * In addition, we've set stathz and profhz.
232 printf("clock: hz=%d stathz=%d\n", hz
, stathz
);
234 _timer_intr_dis(clock_sc
);
235 _timer_intr_dis(stat_sc
);
236 _timer_intr_dis(ref_sc
);
238 setclockrate(clock_sc
, hz
);
239 setclockrate(stat_sc
, stathz
);
240 setclockrate(ref_sc
, 0);
244 * The "cookie" parameter must be zero to pass the interrupt frame
245 * through to hardclock() and statclock().
248 intr_establish(clock_sc
->sc_intr
, IPL_CLOCK
, IST_LEVEL
, clockintr
, 0);
249 intr_establish(stat_sc
->sc_intr
, IPL_HIGH
, IST_LEVEL
, statintr
, 0);
251 _timer_intr_enb(clock_sc
);
252 _timer_intr_enb(stat_sc
);
254 tc_init(&mpu_timecounter
);
261 uint32_t cur
, last
, delta
, usecs
;
263 if (clock_sc
== NULL
)
264 panic("The timer must be initialized sooner.");
267 * This works by polling the timer and counting the
268 * number of microseconds that go by.
270 last
= _timer_read(clock_sc
);
275 cur
= _timer_read(clock_sc
);
277 /* Check to see if the timer has wrapped around. */
279 delta
+= (last
+ (counts_per_hz
- cur
));
281 delta
+= (last
- cur
);
285 if (delta
>= counts_per_usec
) {
286 usecs
+= delta
/ counts_per_usec
;
287 delta
%= counts_per_usec
;
291 #endif /* ARM11_PMC */
295 * (0xFFFFFFFF - GPTn.TLDR + 1) * (timer functional clock period) * PS
298 calc_timer_factors(int ints_per_sec
, timer_factors
*tf
)
300 uint32_t ptv_power
; /* PS */
302 const uint32_t us_per_sec
= 1000000;
304 if (ints_per_sec
== 0) {
306 * When ints_per_sec equal to zero there is mean full range
307 * timer usage. Nevertheless autoreload mode is still enabled.
311 tf
->counts_per_usec
= OMAP_MPU_TIMER_CLOCK_FREQ
/ us_per_sec
;
318 ptv_power
= 1 << tf
->ptv
;
319 count_freq
= OMAP_MPU_TIMER_CLOCK_FREQ
;
321 count_freq
/= ptv_power
;
322 tf
->reload
= -count_freq
;
323 tf
->counts_per_usec
= count_freq
/ us_per_sec
;
324 if ((tf
->reload
* ptv_power
* ints_per_sec
325 == OMAP_MPU_TIMER_CLOCK_FREQ
)
326 && (tf
->counts_per_usec
* ptv_power
* us_per_sec
327 == OMAP_MPU_TIMER_CLOCK_FREQ
))
328 { /* Exact match. Life is good. */
329 /* Currently reload is MPU_LOAD_TIMER+1. Fix it. */
334 tf
->counts_per_usec
++;