xref: /netbsd/sys/arch/sbmips/sbmips/systemsw.c (revision bf9ec67e)
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