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