xref: /netbsd/sys/arch/sbmips/sbmips/systemsw.c (revision c4a72b64)
1 /* $NetBSD: systemsw.c,v 1.6 2002/06/04 05:42:41 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 /* system function switch */
55 struct systemsw systemsw = {
56 	cpu_intr_triv,
57 	cpu_setsoftintr_triv,
58 	microtime_triv,
59 	clkread_triv,
60 	delay_triv,
61 
62 	NULL,			/* clock intr arg */
63 	clock_init_triv,
64 
65 	NULL,			/* statclock arg */
66 	NULL,			/* s_statclock_init: dflt no-op */
67 	NULL,			/* s_statclock_setrate: dflt no-op */
68 
69 	NULL,			/* todr functions arg */
70 	inittodr_triv,
71 	resettodr_triv,
72 	NULL,			/* 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 int
87 system_set_todrfns(void *arg, void (*init)(void *, time_t),
88     void (*reset)(void *))
89 {
90 
91 	if (systemsw.s_inittodr != inittodr_triv ||
92 	    systemsw.s_resettodr != resettodr_triv)
93 		return 1;
94 	systemsw.s_todr_arg = arg;
95 	systemsw.s_inittodr = init;
96 	systemsw.s_resettodr = reset;
97 	return 0;
98 }
99 
100 
101 /* trivial microtime() implementation */
102 static void
103 microtime_triv(struct timeval *tvp)
104 {
105 	int s;
106 	static struct timeval lasttime;
107 
108 	s = splclock();
109 	*tvp = time;
110 
111 	if (systemsw.s_clkread)
112 		tvp->tv_usec += systemsw.s_clkread();
113 
114 	if (tvp->tv_usec >= 1000000) {
115 		tvp->tv_usec -= 1000000;
116 		tvp->tv_sec++;
117 	}
118 
119 	if (tvp->tv_sec == lasttime.tv_sec &&
120 	    tvp->tv_usec <= lasttime.tv_usec &&
121 	    (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
122 		tvp->tv_sec++;
123 		tvp->tv_usec -= 1000000;
124 	}
125 	lasttime = *tvp;
126 
127 	splx(s);
128 }
129 
130 static uint32_t
131 clkread_triv(void)
132 {
133 	uint32_t res, count;
134 
135 	count = mips3_cp0_count_read();
136 	MIPS_COUNT_TO_MHZ(curcpu(), count, res);
137 	return (res);
138 }
139 
140 
141 /* trivial delay() implementation */
142 static void
143 delay_triv(u_long n)
144 {
145 	u_long i;
146 	long divisor = curcpu()->ci_divisor_delay;
147 
148 	while (n-- > 0)
149 		for (i = divisor; i > 0; i--)
150 			;
151 }
152 
153 static void
154 cpu_intr_triv(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending)
155 {
156 
157 	panic("cpu_intr_triv");
158 }
159 
160 void
161 cpu_setsoftintr_triv(void)
162 {
163 	panic("cpu_setsoftintr_triv");
164 }
165 
166 void
167 cpu_intr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending)
168 {
169 
170 	(*systemsw.s_cpu_intr)(status, cause, pc, ipending);
171 }
172 
173 void
174 microtime(struct timeval *tvp)
175 {
176 
177 	(*systemsw.s_microtime)(tvp);
178 }
179 
180 static void
181 clock_init_triv(void *arg)
182 {
183 
184 	panic("clock_init_triv");
185 }
186 
187 static void
188 inittodr_triv(void *arg, time_t t)
189 {
190 
191 	time.tv_sec = t;
192 }
193 
194 static void
195 resettodr_triv(void *arg)
196 {
197 
198 	/* do nothing */
199 }
200 
201 void
202 cpu_initclocks(void)
203 {
204 
205 	(*systemsw.s_clock_init)(systemsw.s_clock_arg);
206 
207 	if (systemsw.s_statclock_init != NULL)
208 		(*systemsw.s_statclock_init)(systemsw.s_statclock_arg);
209 
210 	/*
211 	 * ``Disable'' the compare interrupt by setting it to it's largest
212 	 * value.  The counter will be reset to 0 every hz.  This is used
213 	 * for microtime.
214 	 */
215 	mips3_cp0_compare_write(~(uint32_t)0);
216 	mips3_cp0_count_write(0);
217 }
218 
219 void
220 setstatclockrate(int hzrate)
221 {
222 
223 	if (systemsw.s_statclock_setrate != NULL)
224 		(*systemsw.s_statclock_setrate)(systemsw.s_statclock_arg,
225 		    hzrate);
226 }
227 
228 void
229 inittodr(time_t t)
230 {
231 
232 	(*systemsw.s_inittodr)(systemsw.s_todr_arg, t);
233 }
234 
235 void
236 resettodr(void)
237 {
238 
239 	(*systemsw.s_resettodr)(systemsw.s_todr_arg);
240 }
241