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