clock.c revision 178367
1/*-
2 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
3 * Copyright (C) 1995, 1996 TooLs GmbH.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by TooLs GmbH.
17 * 4. The name of TooLs GmbH may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 *	$NetBSD: clock.c,v 1.9 2000/01/19 02:52:19 msaitoh Exp $
32 */
33/*
34 * Copyright (C) 2001 Benno Rice.
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 */
57
58#include <sys/cdefs.h>
59__FBSDID("$FreeBSD: head/sys/powerpc/aim/clock.c 178367 2008-04-21 04:41:37Z marcel $");
60
61#include <sys/param.h>
62#include <sys/systm.h>
63#include <sys/kernel.h>
64#include <sys/sysctl.h>
65#include <sys/bus.h>
66#include <sys/clock.h>
67#include <sys/timetc.h>
68#include <sys/interrupt.h>
69
70#include <dev/ofw/openfirm.h>
71
72#include <machine/clock.h>
73#include <machine/cpu.h>
74#include <machine/intr.h>
75#include <machine/md_var.h>
76
77/*
78 * Initially we assume a processor with a bus frequency of 12.5 MHz.
79 */
80u_int			tickspending;
81u_long			ns_per_tick = 80;
82static u_long		ticks_per_sec = 12500000;
83static long		ticks_per_intr;
84static volatile u_long	lasttb;
85
86static timecounter_get_t	decr_get_timecount;
87
88static struct timecounter	decr_timecounter = {
89	decr_get_timecount,	/* get_timecount */
90	0,			/* no poll_pps */
91	~0u,			/* counter_mask */
92	0,			/* frequency */
93	"decrementer"		/* name */
94};
95
96void
97decr_intr(struct trapframe *frame)
98{
99	u_long		tb;
100	long		tick;
101	int		nticks;
102
103	/*
104	 * Check whether we are initialized.
105	 */
106	if (!ticks_per_intr)
107		return;
108
109	/*
110	 * Based on the actual time delay since the last decrementer reload,
111	 * we arrange for earlier interrupt next time.
112	 */
113	__asm ("mftb %0; mfdec %1" : "=r"(tb), "=r"(tick));
114	for (nticks = 0; tick < 0; nticks++)
115		tick += ticks_per_intr;
116	mtdec(tick);
117	/*
118	 * lasttb is used during microtime. Set it to the virtual
119	 * start of this tick interval.
120	 */
121	lasttb = tb + tick - ticks_per_intr;
122
123	nticks += tickspending;
124	tickspending = 0;
125
126	/*
127	 * Reenable interrupts
128	 */
129#if 0
130	msr = mfmsr();
131	mtmsr(msr | PSL_EE | PSL_RI);
132#endif
133	/*
134	 * Do standard timer interrupt stuff.
135	 * Do softclock stuff only on the last iteration.
136	 */
137#if 0
138	while (--nticks > 0) {
139		hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
140	}
141#endif
142	hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
143}
144
145void
146decr_init(void)
147{
148	int qhandle, phandle;
149	char name[32];
150	unsigned int msr;
151
152	phandle = 0;
153
154	/*
155	 * Get this info during autoconf?				XXX
156	 */
157	for (qhandle = OF_peer(0); qhandle; qhandle = phandle) {
158		if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0
159		    && !strcmp(name, "cpu")
160		    && OF_getprop(qhandle, "timebase-frequency",
161				  &ticks_per_sec, sizeof ticks_per_sec) >= 0) {
162			/*
163			 * Should check for correct CPU here?		XXX
164			 */
165			msr = mfmsr();
166			mtmsr(msr & ~(PSL_EE|PSL_RI));
167
168			ns_per_tick = 1000000000 / ticks_per_sec;
169			ticks_per_intr = ticks_per_sec / hz;
170			__asm __volatile ("mftb %0" : "=r"(lasttb));
171			mtdec(ticks_per_intr);
172
173			mtmsr(msr);
174
175			break;
176		}
177		if ((phandle = OF_child(qhandle)))
178			continue;
179		while (qhandle) {
180			if ((phandle = OF_peer(qhandle)))
181				break;
182			qhandle = OF_parent(qhandle);
183		}
184	}
185	if (!phandle)
186		panic("no cpu node");
187}
188
189void
190decr_tc_init(void)
191{
192	decr_timecounter.tc_frequency = ticks_per_sec;
193	tc_init(&decr_timecounter);
194}
195
196static __inline u_quad_t
197mftb(void)
198{
199	u_long		scratch;
200	u_quad_t	tb;
201
202	__asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw 0,%0,%1; bne 1b"
203	      : "=r"(tb), "=r"(scratch));
204	return tb;
205}
206
207static unsigned
208decr_get_timecount(struct timecounter *tc)
209{
210	return mftb();
211}
212
213/*
214 * Wait for about n microseconds (at least!).
215 */
216void
217DELAY(int n)
218{
219	u_quad_t	tb, ttb;
220
221	tb = mftb();
222	ttb = tb + (n * 1000 + ns_per_tick - 1) / ns_per_tick;
223	while (tb < ttb)
224		tb = mftb();
225}
226
227/*
228 * Nothing to do.
229 */
230void
231cpu_startprofclock(void)
232{
233
234	/* Do nothing */
235}
236
237void
238cpu_stopprofclock(void)
239{
240}
241