vr.c revision 1.30 1 /* $NetBSD: vr.c,v 1.30 2001/09/17 17:03:46 uch Exp $ */
2
3 /*-
4 * Copyright (c) 1999
5 * Shin Takemura and PocketBSD Project. 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 PocketBSD project
18 * and its contributors.
19 * 4. Neither the name of the project nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 */
36
37 #include "opt_vr41xx.h"
38 #include "opt_kgdb.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/reboot.h>
43
44 #include <machine/sysconf.h>
45 #include <machine/bus.h>
46 #include <machine/bootinfo.h>
47
48 #include <dev/hpc/hpckbdvar.h>
49
50 #include <hpcmips/hpcmips/machdep.h> /* cpu_name, mem_cluster */
51
52 #include <hpcmips/vr/vr.h>
53 #include <hpcmips/vr/vr_asm.h>
54 #include <hpcmips/vr/vrcpudef.h>
55 #include <hpcmips/vr/vripreg.h>
56 #include <hpcmips/vr/rtcreg.h>
57
58 #include "vrip.h"
59 #if NVRIP > 0
60 #include <hpcmips/vr/vripvar.h>
61 #endif
62
63 #include "vrbcu.h"
64 #if NVRBCU > 0
65 #include <hpcmips/vr/bcuvar.h>
66 #endif
67
68 #include "vrdsu.h"
69 #if NVRDSU > 0
70 #include <hpcmips/vr/vrdsuvar.h>
71 #endif
72
73 #include "com.h"
74 #if NCOM > 0
75 #include <sys/termios.h>
76 #include <sys/ttydefaults.h>
77 #include <dev/ic/comreg.h>
78 #include <dev/ic/comvar.h>
79 #include <hpcmips/vr/siureg.h>
80 #include <hpcmips/vr/com_vripvar.h>
81 #ifndef CONSPEED
82 #define CONSPEED TTYDEF_SPEED
83 #endif
84 #endif
85
86 #include "hpcfb.h"
87 #include "vrkiu.h"
88 #if (NVRKIU > 0) || (NHPCFB > 0)
89 #include <dev/wscons/wsdisplayvar.h>
90 #include <dev/rasops/rasops.h>
91 #endif
92
93 #if NHPCFB > 0
94 #include <dev/hpc/hpcfbvar.h>
95 #endif
96
97 #if NVRKIU > 0
98 #include <arch/hpcmips/vr/vrkiureg.h>
99 #include <arch/hpcmips/vr/vrkiuvar.h>
100 #endif
101
102 void vr_init(void);
103 int vr_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
104 void vr_cons_init(void);
105 void vr_fb_init(caddr_t *);
106 void vr_mem_init(paddr_t);
107 void vr_find_dram(paddr_t, paddr_t);
108 void vr_reboot(int, char *);
109 void vr_idle(void);
110
111 /*
112 * CPU interrupt dispatch table (HwInt[0:3])
113 */
114 int null_handler(void *, u_int32_t, u_int32_t);
115 static int (*intr_handler[4])(void*, u_int32_t, u_int32_t) =
116 {
117 null_handler,
118 null_handler,
119 null_handler,
120 null_handler
121 };
122 static void *intr_arg[4];
123
124 void
125 vr_init()
126 {
127 /*
128 * Platform Specific Function Hooks
129 */
130 platform.cpu_idle = vr_idle;
131 platform.iointr = vr_intr;
132 platform.cons_init = vr_cons_init;
133 platform.fb_init = vr_fb_init;
134 platform.mem_init = vr_mem_init;
135 platform.reboot = vr_reboot;
136
137 #if NVRBCU > 0
138 sprintf(cpu_name, "NEC %s rev%d.%d %d.%03dMHz",
139 vrbcu_vrip_getcpuname(),
140 vrbcu_vrip_getcpumajor(),
141 vrbcu_vrip_getcpuminor(),
142 vrbcu_vrip_getcpuclock() / 1000000,
143 (vrbcu_vrip_getcpuclock() % 1000000) / 1000);
144 #else
145 sprintf(cpu_name, "NEC VR41xx");
146 #endif
147 }
148
149 void
150 vr_mem_init(paddr_t kernend)
151 {
152
153 mem_clusters[0].start = 0;
154 mem_clusters[0].size = kernend;
155 mem_cluster_cnt = 1;
156
157 vr_find_dram(kernend, 0x02000000);
158 vr_find_dram(0x02000000, 0x04000000);
159 vr_find_dram(0x04000000, 0x06000000);
160 vr_find_dram(0x06000000, 0x08000000);
161
162 /* Clear currently unused D-RAM area (For reboot Windows CE clearly)*/
163 memset((void *)(KERNBASE + 0x400), 0, KERNTEXTOFF - (KERNBASE + 0x800));
164 }
165
166 void
167 vr_find_dram(paddr_t addr, paddr_t end)
168 {
169 int n;
170 caddr_t page;
171 #ifdef NARLY_MEMORY_PROBE
172 int x, i;
173 #endif
174
175 #ifdef VR_FIND_DRAMLIM
176 if (VR_FIND_DRAMLIM < end)
177 end = VR_FIND_DRAMLIM;
178 #endif
179 n = mem_cluster_cnt;
180 for (; addr < end; addr += NBPG) {
181
182 page = (void *)MIPS_PHYS_TO_KSEG1(addr);
183 if (badaddr(page, 4))
184 goto bad;
185
186 /* stop memory probing at first memory image */
187 if (bcmp(page, (void *)MIPS_PHYS_TO_KSEG0(0), 128) == 0)
188 return;
189
190 *(volatile int *)(page+0) = 0xa5a5a5a5;
191 *(volatile int *)(page+4) = 0x5a5a5a5a;
192 wbflush();
193 if (*(volatile int *)(page+0) != 0xa5a5a5a5)
194 goto bad;
195
196 *(volatile int *)(page+0) = 0x5a5a5a5a;
197 *(volatile int *)(page+4) = 0xa5a5a5a5;
198 wbflush();
199 if (*(volatile int *)(page+0) != 0x5a5a5a5a)
200 goto bad;
201
202 #ifdef NARLY_MEMORY_PROBE
203 x = random();
204 for (i = 0; i < NBPG; i += 4)
205 *(volatile int *)(page+i) = (x ^ i);
206 wbflush();
207 for (i = 0; i < NBPG; i += 4)
208 if (*(volatile int *)(page+i) != (x ^ i))
209 goto bad;
210
211 x = random();
212 for (i = 0; i < NBPG; i += 4)
213 *(volatile int *)(page+i) = (x ^ i);
214 wbflush();
215 for (i = 0; i < NBPG; i += 4)
216 if (*(volatile int *)(page+i) != (x ^ i))
217 goto bad;
218 #endif
219
220 if (!mem_clusters[n].size)
221 mem_clusters[n].start = addr;
222 mem_clusters[n].size += NBPG;
223 continue;
224
225 bad:
226 if (mem_clusters[n].size)
227 ++n;
228 continue;
229 }
230 if (mem_clusters[n].size)
231 ++n;
232 mem_cluster_cnt = n;
233 }
234
235 void
236 vr_fb_init(caddr_t *kernend)
237 {
238 /* Nothing to do */
239 }
240
241 void
242 vr_cons_init()
243 {
244 #if NCOM > 0 || NHPCFB > 0 || NVRKIU > 0
245 bus_space_tag_t iot = hpcmips_system_bus_space();
246 #endif
247
248 #if NCOM > 0
249 #ifdef KGDB
250 /* if KGDB is defined, always use the serial port for KGDB */
251 if (com_vrip_cndb_attach(iot, VRIP_SIU_ADDR, 9600, VRCOM_FREQ,
252 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8, 1)) {
253 printf("%s(%d): can't init kgdb's serial port",
254 __FILE__, __LINE__);
255 }
256 #else /* KGDB */
257 if (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) {
258 /* Serial console */
259 if (com_vrip_cndb_attach(iot, VRIP_SIU_ADDR, CONSPEED,
260 VRCOM_FREQ, (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8, 0)) {
261 printf("%s(%d): can't init serial console",
262 __FILE__, __LINE__);
263 } else {
264 return;
265 }
266 }
267 #endif /* KGDB */
268 #endif /* NCOM > 0 */
269
270 #if NHPCFB > 0
271 if (hpcfb_cnattach(NULL)) {
272 printf("%s(%d): can't init fb console", __FILE__, __LINE__);
273 } else {
274 goto find_keyboard;
275 }
276 find_keyboard:
277 #endif /* NHPCFB > 0 */
278
279 #if NVRKIU > 0 && VRIP_KIU_ADDR != VRIP_NO_ADDR
280 if (vrkiu_cnattach(iot, VRIP_KIU_ADDR)) {
281 printf("%s(%d): can't init vrkiu as console",
282 __FILE__, __LINE__);
283 } else {
284 return;
285 }
286 #endif /* NVRKIU > 0 && VRIP_KIU_ADDR != VRIP_NO_ADDR */
287 }
288
289 void
290 vr_reboot(int howto, char *bootstr)
291 {
292 /*
293 * power down
294 */
295 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
296 printf("fake powerdown\n");
297 __asm(__CONCAT(".word ",___STRING(VR_OPCODE_HIBERNATE)));
298 __asm("nop");
299 __asm("nop");
300 __asm("nop");
301 __asm("nop");
302 __asm("nop");
303 __asm(".set reorder");
304 /* not reach */
305 vr_reboot(howto&~RB_HALT, bootstr);
306 }
307 /*
308 * halt
309 */
310 if (howto & RB_HALT) {
311 #if NVRIP > 0
312 _spllower(~MIPS_INT_MASK_0);
313 vrip_intr_suspend();
314 #else
315 splhigh();
316 #endif
317 __asm(".set noreorder");
318 __asm(__CONCAT(".word ",___STRING(VR_OPCODE_SUSPEND)));
319 __asm("nop");
320 __asm("nop");
321 __asm("nop");
322 __asm("nop");
323 __asm("nop");
324 __asm(".set reorder");
325 #if NVRIP > 0
326 vrip_intr_resume();
327 #endif
328 }
329 /*
330 * reset
331 */
332 #if NVRDSU
333 vrdsu_reset();
334 #else
335 printf("%s(%d): There is no DSU.", __FILE__, __LINE__);
336 #endif
337 }
338
339 /*
340 * Handle interrupts.
341 */
342 int
343 vr_intr(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending)
344 {
345 int hwintr;
346
347 hwintr = (ffs(ipending >> 10) -1) & 0x3;
348 (*intr_handler[hwintr])(intr_arg[hwintr], pc, status);
349
350 return (MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK));
351 }
352
353 void *
354 vr_intr_establish(int line, int (*ih_fun)(void *, u_int32_t, u_int32_t),
355 void *ih_arg)
356 {
357
358 if (intr_handler[line] != null_handler) {
359 panic("vr_intr_establish:"
360 " can't establish duplicated intr handler.");
361 }
362 intr_handler[line] = ih_fun;
363 intr_arg[line] = ih_arg;
364
365 return ((void*)line);
366 }
367
368
369 void
370 vr_intr_disestablish(void *ih)
371 {
372 int line = (int)ih;
373
374 intr_handler[line] = null_handler;
375 intr_arg[line] = NULL;
376 }
377
378 int
379 null_handler(void *arg, u_int32_t pc, u_int32_t statusReg)
380 {
381 printf("null_handler\n");
382
383 return (0);
384 }
385
386 /*
387 int x4181 = VR4181;
388 int x4101 = VR4101;
389 int x4102 = VR4102;
390 int x4111 = VR4111;
391 int x4121 = VR4121;
392 int x4122 = VR4122;
393 int xo4181 = ONLY_VR4181;
394 int xo4101 = ONLY_VR4101;
395 int xo4102 = ONLY_VR4102;
396 int xo4111_4121 = ONLY_VR4111_4121;
397 int g4101=VRGROUP_4101;
398 int g4102=VRGROUP_4102;
399 int g4181=VRGROUP_4181;
400 int g4102_4121=VRGROUP_4102_4121;
401 int g4111_4121=VRGROUP_4111_4121;
402 int g4102_4122=VRGROUP_4102_4122;
403 int g4111_4122=VRGROUP_4111_4122;
404 int single_vrip_base=SINGLE_VRIP_BASE;
405 int vrip_base_addr=VRIP_BASE_ADDR;
406 */
407