1 /* $NetBSD: systemsw.c,v 1.4 2002/05/03 03:36:51 simonb Exp $ */ 2 3 /* 4 * Copyright 2000, 2001 5 * Broadcom Corporation. All rights reserved. 6 * 7 * This software is furnished under license and may be used and copied only 8 * in accordance with the following terms and conditions. Subject to these 9 * conditions, you may download, copy, install, use, modify and distribute 10 * modified or unmodified copies of this software in source and/or binary 11 * form. No title or ownership is transferred hereby. 12 * 13 * 1) Any source code used, modified or distributed must reproduce and 14 * retain this copyright notice and list of conditions as they appear in 15 * the source file. 16 * 17 * 2) No right is granted to use any trade name, trademark, or logo of 18 * Broadcom Corporation. Neither the "Broadcom Corporation" name nor any 19 * trademark or logo of Broadcom Corporation may be used to endorse or 20 * promote products derived from this software without the prior written 21 * permission of Broadcom Corporation. 22 * 23 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 24 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 26 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 27 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 28 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 40 #include <mips/locore.h> 41 #include <machine/intr.h> 42 #include <machine/systemsw.h> 43 44 /* trivial functions for function switch */ 45 static void clock_init_triv(void *); 46 static uint32_t clkread_triv(void); 47 static void cpu_intr_triv(uint32_t, uint32_t, uint32_t, uint32_t); 48 static void cpu_setsoftintr_triv(void); 49 static void delay_triv(u_long); 50 static void inittodr_triv(void *, time_t); 51 static void microtime_triv(struct timeval *); 52 static void resettodr_triv(void *); 53 54 #define XXXNULL NULL 55 56 /* system function switch */ 57 struct systemsw systemsw = { 58 cpu_intr_triv, 59 cpu_setsoftintr_triv, 60 microtime_triv, 61 clkread_triv, 62 delay_triv, 63 64 NULL, /* clock intr arg */ 65 clock_init_triv, 66 67 NULL, /* s_statclock_init: dflt no-op */ 68 NULL, /* s_statclock_setrate: dflt no-op */ 69 70 inittodr_triv, 71 resettodr_triv, 72 NULL, /* XXX: s_intr_establish */ 73 }; 74 75 int 76 system_set_clockfns(void *arg, void (*init)(void *)) 77 { 78 79 if (systemsw.s_clock_init != clock_init_triv) 80 return 1; 81 systemsw.s_clock_arg = arg; 82 systemsw.s_clock_init = init; 83 return 0; 84 } 85 86 /* trivial microtime() implementation */ 87 static void 88 microtime_triv(struct timeval *tvp) 89 { 90 int s; 91 static struct timeval lasttime; 92 93 s = splclock(); 94 *tvp = time; 95 96 if (systemsw.s_clkread) 97 tvp->tv_usec += systemsw.s_clkread(); 98 99 if (tvp->tv_usec >= 1000000) { 100 tvp->tv_usec -= 1000000; 101 tvp->tv_sec++; 102 } 103 104 if (tvp->tv_sec == lasttime.tv_sec && 105 tvp->tv_usec <= lasttime.tv_usec && 106 (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { 107 tvp->tv_sec++; 108 tvp->tv_usec -= 1000000; 109 } 110 lasttime = *tvp; 111 112 splx(s); 113 } 114 115 static uint32_t 116 clkread_triv(void) 117 { 118 uint32_t res, count; 119 120 count = mips3_cp0_count_read(); 121 122 asm volatile("multu %1,%2 ; mfhi %0" 123 : "=r"(res) : "r"(count), "r"(curcpu()->ci_divisor_recip)); 124 125 return (res); 126 } 127 128 129 /* trivial delay() implementation */ 130 static void 131 delay_triv(u_long n) 132 { 133 u_long i; 134 long divisor = curcpu()->ci_divisor_delay; 135 136 while (n-- > 0) 137 for (i = divisor; i > 0; i--) 138 ; 139 } 140 141 static void 142 cpu_intr_triv(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending) 143 { 144 145 panic("cpu_intr_triv"); 146 } 147 148 void 149 cpu_setsoftintr_triv(void) 150 { 151 panic("cpu_setsoftintr_triv"); 152 } 153 154 void 155 cpu_intr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending) 156 { 157 158 (*systemsw.s_cpu_intr)(status, cause, pc, ipending); 159 } 160 161 void 162 microtime(struct timeval *tvp) 163 { 164 165 (*systemsw.s_microtime)(tvp); 166 } 167 168 static void 169 clock_init_triv(void *arg) 170 { 171 panic("clock_init_triv"); 172 } 173 174 static void 175 inittodr_triv(void *arg, time_t t) 176 { 177 178 time.tv_sec = t; 179 } 180 181 static void 182 resettodr_triv(void *arg) 183 { 184 185 /* do nothing */ 186 } 187 188 void 189 cpu_initclocks(void) 190 { 191 192 (*systemsw.s_clock_init)(systemsw.s_clock_arg); 193 194 if (systemsw.s_statclock_init != NULL) 195 (*systemsw.s_statclock_init)(XXXNULL); 196 197 /* 198 * ``Disable'' the compare interrupt by setting it to it's largest 199 * value. The counter will be reset to 0 every hz. This is used 200 * for microtime. 201 */ 202 mips3_cp0_compare_write(~(uint32_t)0); 203 mips3_cp0_count_write(0); 204 } 205 206 void 207 setstatclockrate(int hzrate) 208 { 209 210 if (systemsw.s_statclock_setrate != NULL) 211 (*systemsw.s_statclock_setrate)(XXXNULL, hzrate); 212 } 213 214 void 215 inittodr(time_t t) 216 { 217 218 (*systemsw.s_inittodr)(XXXNULL, t); 219 } 220 221 void 222 resettodr(void) 223 { 224 225 (*systemsw.s_resettodr)(XXXNULL); 226 } 227