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 #ifndef lint
59 static const char rcsid[] =
60 "$FreeBSD: releng/5.0/sys/powerpc/powerpc/clock.c 99032 2002-06-29 09:28:21Z benno $";
61 #endif /* not lint */
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
66 #include <sys/sysctl.h>
67 #include <sys/bus.h>
68 #include <sys/timetc.h>
69 #include <sys/interrupt.h>
70
71 #include <dev/ofw/openfirm.h>
72
73 #include <machine/clock.h>
74 #include <machine/cpu.h>
75 #include <machine/intr.h>
76
77 #if 0 /* XXX */
78 #include "adb.h"
79 #else
80 #define NADB 0
81 #endif
82
83 /*
84 * Initially we assume a processor with a bus frequency of 12.5 MHz.
85 */
86 u_int tickspending;
87 static u_long ticks_per_sec = 12500000;
88 static u_long ns_per_tick = 80;
89 static long ticks_per_intr;
90 static volatile u_long lasttb;
91
92 #define SECDAY 86400
93 #define DIFF19041970 2082844800
94
95 #if NADB > 0
96 extern int adb_read_date_time(int *);
97 extern int adb_set_date_time(int);
98 #endif
99
100 static int clockinitted = 0;
101
102 static timecounter_get_t powerpc_get_timecount;
103
104 static struct timecounter powerpc_timecounter = {
105 powerpc_get_timecount, /* get_timecount */
106 0, /* no poll_pps */
107 ~0u, /* counter_mask */
108 0, /* frequency */
109 "powerpc" /* name */
110 };
111
112 void
113 inittodr(time_t base)
114 {
115 time_t deltat;
116 u_int rtc_time;
117 struct timespec ts;
118
119 /*
120 * If we can't read from RTC, use the fs time.
121 */
122 #if NADB > 0
123 if (adb_read_date_time(&rtc_time) < 0)
124 #endif
125 {
126 ts.tv_sec = base;
127 ts.tv_nsec = 0;
128 tc_setclock(&ts);
129 return;
130 }
131 clockinitted = 1;
132 ts.tv_sec = rtc_time - DIFF19041970;
133
134 deltat = ts.tv_sec - base;
135 if (deltat < 0) {
136 deltat = -deltat;
137 }
138 if (deltat < 2 * SECDAY) {
139 tc_setclock(&ts);
140 return;
141 }
142
143 printf("WARNING: clock %s %d days",
144 ts.tv_sec < base ? "lost" : "gained", (int)(deltat / SECDAY));
145
146 printf(" -- CHECK AND RESET THE DATE!\n");
147 }
148
149 /*
150 * Similar to the above
151 */
152 void
153 resettodr()
154 {
155 #if NADB > 0
156 u_int rtc_time;
157
158 if (clockinitted) {
159 rtc_time = time.tv_sec + DIFF19041970;
160 adb_set_date_time(rtc_time);
161 }
162 #endif
163 }
164
165 void
166 decr_intr(struct clockframe *frame)
167 {
168 u_long tb;
169 long tick;
170 int nticks;
171 register_t msr;
172
173 /*
174 * Check whether we are initialized.
175 */
176 if (!ticks_per_intr)
177 return;
178
179 /*
180 * Based on the actual time delay since the last decrementer reload,
181 * we arrange for earlier interrupt next time.
182 */
183 __asm ("mftb %0; mfdec %1" : "=r"(tb), "=r"(tick));
184 for (nticks = 0; tick < 0; nticks++)
185 tick += ticks_per_intr;
186 mtdec(tick);
187 /*
188 * lasttb is used during microtime. Set it to the virtual
189 * start of this tick interval.
190 */
191 lasttb = tb + tick - ticks_per_intr;
192
193 nticks += tickspending;
194 tickspending = 0;
195
196 /*
197 * Reenable interrupts
198 */
199 #if 0
200 msr = mfmsr();
201 mtmsr(msr | PSL_EE | PSL_RI);
202 #endif
203 /*
204 * Do standard timer interrupt stuff.
205 * Do softclock stuff only on the last iteration.
206 */
207 #if 0
208 while (--nticks > 0) {
209 hardclock(frame);
210 }
211 #endif
212 hardclock(frame);
213 }
214
215 void
216 cpu_initclocks(void)
217 {
218 int qhandle, phandle;
219 char name[32];
220 unsigned int msr;
221
222 phandle = 0;
223
224 /*
225 * Get this info during autoconf? XXX
226 */
227 for (qhandle = OF_peer(0); qhandle; qhandle = phandle) {
228 if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0
229 && !strcmp(name, "cpu")
230 && OF_getprop(qhandle, "timebase-frequency",
231 &ticks_per_sec, sizeof ticks_per_sec) >= 0) {
232 /*
233 * Should check for correct CPU here? XXX
234 */
235 msr = mfmsr();
236 mtmsr(msr & ~(PSL_EE|PSL_RI));
237
238 powerpc_timecounter.tc_frequency = ticks_per_sec;
239 tc_init(&powerpc_timecounter);
240
241 ns_per_tick = 1000000000 / ticks_per_sec;
242 ticks_per_intr = ticks_per_sec / hz;
243 __asm __volatile ("mftb %0" : "=r"(lasttb));
244 mtdec(ticks_per_intr);
245
246 mtmsr(msr);
247
248 break;
249 }
250 if ((phandle = OF_child(qhandle)))
251 continue;
252 while (qhandle) {
253 if ((phandle = OF_peer(qhandle)))
254 break;
255 qhandle = OF_parent(qhandle);
256 }
257 }
258 if (!phandle)
259 panic("no cpu node");
260 }
261
262 static __inline u_quad_t
263 mftb(void)
264 {
265 u_long scratch;
266 u_quad_t tb;
267
268 __asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw 0,%0,%1; bne 1b"
269 : "=r"(tb), "=r"(scratch));
270 return tb;
271 }
272
273 static unsigned
274 powerpc_get_timecount(struct timecounter *tc)
275 {
276 return mftb();
277 }
278
279 /*
280 * Wait for about n microseconds (at least!).
281 */
282 void
283 delay(int n)
284 {
285 u_quad_t tb;
286 u_long tbh, tbl, scratch;
287
288 tb = mftb();
289 tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
290 tbh = tb >> 32;
291 tbl = tb;
292 __asm ("1: mftbu %0; cmplw %0,%1; blt 1b; bgt 2f;"
293 "mftb %0; cmplw %0,%2; blt 1b; 2:"
294 : "=r"(scratch) : "r"(tbh), "r"(tbl));
295 }
296
297 /*
298 * Nothing to do.
299 */
300 void
301 setstatclockrate(int arg)
302 {
303
304 /* Do nothing */
305 }
Cache object: 6d46b16f4aa92fede10d19a299508b0c
|