1 /*	$NetBSD: clock.c,v 1.1 2001/10/16 15:38:53 uch Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *        This product includes software developed by the NetBSD
18  *        Foundation, Inc. and its contributors.
19  * 4. Neither the name of The NetBSD Foundation nor the names of its
20  *    contributors may be used to endorse or promote products derived
21  *    from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include "debug_playstation2.h"
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>		/* time */
41 
42 #include <mips/locore.h>
43 
44 #include <dev/clock_subr.h>
45 #include <machine/bootinfo.h>
46 
47 #include <playstation2/ee/timervar.h>
48 
49 #define MINYEAR		2001	/* "today" */
50 
51 static void get_bootinfo_tod(struct clock_ymdhms *);
52 
53 void
54 cpu_initclocks()
55 {
56 
57 	hz = 100;
58 
59 	/* Install clock interrupt */
60 	timer_clock_init();
61 }
62 
63 void
64 inittodr(time_t base)
65 {
66 	struct clock_ymdhms dt;
67 	time_t rtc;
68 	int s;
69 
70 	get_bootinfo_tod(&dt);
71 
72 	rtc = clock_ymdhms_to_secs(&dt);
73 
74 	if (rtc < base ||
75 	    dt.dt_year < MINYEAR || dt.dt_year > 2037 ||
76 	    dt.dt_mon < 1 || dt.dt_mon > 12 ||
77 	    dt.dt_wday > 6 ||
78 	    dt.dt_day < 1 || dt.dt_day > 31 ||
79 	    dt.dt_hour > 23 || dt.dt_min > 59 || dt.dt_sec > 59) {
80 		/*
81 		 * Believe the time in the file system for lack of
82 		 * anything better, resetting the RTC.
83 		 */
84 		s = splclock();
85 		time.tv_sec = base;
86 		time.tv_usec = 0;
87 		splx(s);
88 		printf("WARNING: preposterous clock chip time\n");
89 		resettodr();
90 		printf(" -- CHECK AND RESET THE DATE!\n");
91 		return;
92 	}
93 
94 	s = splclock();
95 	time.tv_sec = rtc + rtc_offset * 60;
96 	time.tv_usec = 0;
97 	splx(s);
98 }
99 
100 void
101 resettodr()
102 {
103 	/* NetBSD kernel can't access PS2 RTC module. nothing to do */
104 }
105 
106 void
107 setstatclockrate(int arg)
108 {
109 	/* not yet */
110 }
111 
112 /*
113  * Return the best possible estimate of the time in the timeval to
114  * which tv points.
115  */
116 void
117 microtime(struct timeval *tvp)
118 {
119 	int s = splclock();
120 	static struct timeval lasttime;
121 
122 	*tvp = time;
123 
124 	if (tvp->tv_usec >= 1000000) {
125 		tvp->tv_usec -= 1000000;
126 		tvp->tv_sec++;
127 	}
128 
129 	if (tvp->tv_sec == lasttime.tv_sec &&
130 	    tvp->tv_usec <= lasttime.tv_usec &&
131 	    (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
132 		tvp->tv_sec++;
133 		tvp->tv_usec -= 1000000;
134 	}
135 	lasttime = *tvp;
136 	splx(s);
137 }
138 
139 /*
140  *  Wait at least `n' usec. (max 15 sec)
141  *  PS2 R5900 CPU clock is 294.912Mhz = (1 << 15) * 9 * 1000
142  */
143 void
144 delay(unsigned usec)
145 {
146 	u_int32_t r0, r1, r2;
147 	u_int64_t n;
148 	int overlap;
149 
150 	r0 = mips3_cp0_count_read();
151 	n = (((u_int64_t)usec * 294912) / 1000) + (u_int64_t)r0;
152 
153 	overlap = n  > 0xffffffff;
154 	r2 = (u_int32_t)(overlap ? 0xffffffff : n);
155 
156 	do {
157 		r1 = mips3_cp0_count_read();
158 	} while (r1 < r2 && r1 > r0);
159 
160 	if (overlap) {
161 		r0 = r1;
162 		r2 = (u_int32_t)(n - 0xffffffff);
163 		do {
164 			r1 = mips3_cp0_count_read();
165 		} while (r1 < r2 && r1 > r0);
166 	}
167 }
168 
169 static void
170 get_bootinfo_tod(struct clock_ymdhms *dt)
171 {
172 	time_t utc;
173 	struct bootinfo_rtc *rtc =
174 	    (void *)MIPS_PHYS_TO_KSEG1(BOOTINFO_BLOCK_BASE + BOOTINFO_RTC);
175 
176 	/* PS2 RTC is JST */
177 	dt->dt_year = FROMBCD(rtc->year) + 2000;
178 	dt->dt_mon = FROMBCD(rtc->mon);
179 	dt->dt_day = FROMBCD(rtc->day);
180 	dt->dt_hour = FROMBCD(rtc->hour);
181 	dt->dt_min = FROMBCD(rtc->min);
182 	dt->dt_sec = FROMBCD(rtc->sec);
183 
184 	/* convert to UTC */
185 	utc = clock_ymdhms_to_secs(dt) - 9*60*60;
186 	clock_secs_to_ymdhms(utc, dt);
187 #ifdef DEBUG
188         printf("bootinfo: %d/%d/%d/%d/%d/%d rtc_offset %d\n", dt->dt_year,
189 	    dt->dt_mon, dt->dt_day, dt->dt_hour, dt->dt_min, dt->dt_sec,
190 	    rtc_offset);
191 #endif
192 }
193