Stop openbios-unix from crashing when auto-boot? is enabled.
[openbios.git] / drivers / obio.c
blobc0db4ff053e180d9efe695f31f0579b401261c1e
1 /*
2 * OpenBIOS Sparc OBIO driver
4 * (C) 2004 Stefan Reinauer <stepan@openbios.org>
5 * (C) 2005 Ed Schouten <ed@fxq.nl>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2
13 #include "config.h"
14 #include "libopenbios/bindings.h"
15 #include "kernel/kernel.h"
16 #include "libc/byteorder.h"
17 #include "libc/vsprintf.h"
19 #include "drivers/drivers.h"
20 #include "arch/common/nvram.h"
21 #include "libopenbios/ofmem.h"
22 #include "obio.h"
23 #define NO_QEMU_PROTOS
24 #include "arch/common/fw_cfg.h"
25 #include "escc.h"
27 #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
29 #define PROMDEV_KBD 0 /* input from keyboard */
30 #define PROMDEV_SCREEN 0 /* output to screen */
31 #define PROMDEV_TTYA 1 /* in/out to ttya */
33 /* "NCPU" is an historical name that's now a bit of a misnomer. The sun4m
34 * architecture registers NCPU CPU-specific interrupts along with one
35 * system-wide interrupt, regardless of the number of actual CPUs installed.
36 * See the comment on "NCPU" at <http://stuff.mit.edu/afs/athena/astaff/
37 * project/opssrc/sys.sunos/sun4m/devaddr.h>.
39 #define SUN4M_NCPU 4
41 /* DECLARE data structures for the nodes. */
42 DECLARE_UNNAMED_NODE( ob_obio, INSTALL_OPEN, sizeof(int) );
44 void
45 ob_new_obio_device(const char *name, const char *type)
47 push_str("/obio");
48 fword("find-device");
49 fword("new-device");
51 push_str(name);
52 fword("device-name");
54 if (type) {
55 push_str(type);
56 fword("device-type");
60 static unsigned long
61 map_reg(uint64_t base, uint64_t offset, unsigned long size, int map,
62 int phys_hi)
64 PUSH(phys_hi);
65 fword("encode-int");
66 PUSH(offset);
67 fword("encode-int");
68 fword("encode+");
69 PUSH(size);
70 fword("encode-int");
71 fword("encode+");
72 push_str("reg");
73 fword("property");
75 if (map) {
76 unsigned long addr;
78 addr = (unsigned long)map_io(base + offset, size);
80 PUSH(addr);
81 fword("encode-int");
82 PUSH(4);
83 fword("encode-int");
84 fword("encode+");
85 push_str("address");
86 fword("property");
87 return addr;
89 return 0;
92 unsigned long
93 ob_reg(uint64_t base, uint64_t offset, unsigned long size, int map)
95 return map_reg(base, offset, size, map, 0);
98 void
99 ob_intr(int intr)
101 PUSH(intr);
102 fword("encode-int");
103 PUSH(0);
104 fword("encode-int");
105 fword("encode+");
106 push_str("intr");
107 fword("property");
110 static void
111 ob_eccmemctl_init(uint64_t base)
113 uint32_t version, *regs;
114 const char *mc_type;
116 push_str("/");
117 fword("find-device");
118 fword("new-device");
120 push_str("eccmemctl");
121 fword("device-name");
123 PUSH(0x20);
124 fword("encode-int");
125 push_str("width");
126 fword("property");
128 regs = (uint32_t *)map_reg(ECC_BASE, 0, ECC_SIZE, 1, ECC_BASE >> 32);
130 version = regs[0];
131 switch (version) {
132 case 0x00000000:
133 mc_type = "MCC";
134 break;
135 case 0x10000000:
136 mc_type = "EMC";
137 break;
138 default:
139 case 0x20000000:
140 mc_type = "SMC";
141 break;
143 push_str(mc_type);
144 fword("encode-string");
145 push_str("mc-type");
146 fword("property");
148 fword("finish-device");
151 static unsigned char *nvram;
153 #define NVRAM_OB_START (0)
154 #define NVRAM_OB_SIZE ((NVRAM_IDPROM - NVRAM_OB_START) & ~15)
156 void
157 arch_nvram_get(char *data)
159 memcpy(data, &nvram[NVRAM_OB_START], NVRAM_OB_SIZE);
162 void
163 arch_nvram_put(char *data)
165 memcpy(&nvram[NVRAM_OB_START], data, NVRAM_OB_SIZE);
169 arch_nvram_size(void)
171 return NVRAM_OB_SIZE;
174 static void mb86904_init(void)
176 PUSH(32);
177 fword("encode-int");
178 push_str("cache-line-size");
179 fword("property");
181 PUSH(512);
182 fword("encode-int");
183 push_str("cache-nlines");
184 fword("property");
186 PUSH(0x23);
187 fword("encode-int");
188 push_str("mask_rev");
189 fword("property");
192 static void tms390z55_init(void)
194 push_str("");
195 fword("encode-string");
196 push_str("ecache-parity?");
197 fword("property");
199 push_str("");
200 fword("encode-string");
201 push_str("bfill?");
202 fword("property");
204 push_str("");
205 fword("encode-string");
206 push_str("bcopy?");
207 fword("property");
209 push_str("");
210 fword("encode-string");
211 push_str("cache-physical?");
212 fword("property");
214 PUSH(0xf);
215 fword("encode-int");
216 PUSH(0xf8fffffc);
217 fword("encode-int");
218 fword("encode+");
219 PUSH(4);
220 fword("encode-int");
221 fword("encode+");
223 PUSH(0xf);
224 fword("encode-int");
225 fword("encode+");
226 PUSH(0xf8c00000);
227 fword("encode-int");
228 fword("encode+");
229 PUSH(0x1000);
230 fword("encode-int");
231 fword("encode+");
233 PUSH(0xf);
234 fword("encode-int");
235 fword("encode+");
236 PUSH(0xf8000000);
237 fword("encode-int");
238 fword("encode+");
239 PUSH(0x1000);
240 fword("encode-int");
241 fword("encode+");
243 PUSH(0xf);
244 fword("encode-int");
245 fword("encode+");
246 PUSH(0xf8800000);
247 fword("encode-int");
248 fword("encode+");
249 PUSH(0x1000);
250 fword("encode-int");
251 fword("encode+");
252 push_str("reg");
253 fword("property");
256 static void rt625_init(void)
258 PUSH(32);
259 fword("encode-int");
260 push_str("cache-line-size");
261 fword("property");
263 PUSH(512);
264 fword("encode-int");
265 push_str("cache-nlines");
266 fword("property");
270 static void bad_cpu_init(void)
272 printk("This CPU is not supported yet, freezing.\n");
273 for(;;);
276 struct cpudef {
277 unsigned long iu_version;
278 const char *name;
279 int psr_impl, psr_vers, impl, vers;
280 int dcache_line_size, dcache_lines, dcache_assoc;
281 int icache_line_size, icache_lines, icache_assoc;
282 int ecache_line_size, ecache_lines, ecache_assoc;
283 int mmu_nctx;
284 void (*initfn)(void);
287 static const struct cpudef sparc_defs[] = {
289 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
290 .name = "FMI,MB86900",
291 .initfn = bad_cpu_init,
294 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
295 .name = "FMI,MB86904",
296 .psr_impl = 0,
297 .psr_vers = 5,
298 .impl = 0,
299 .vers = 5,
300 .dcache_line_size = 0x10,
301 .dcache_lines = 0x200,
302 .dcache_assoc = 1,
303 .icache_line_size = 0x20,
304 .icache_lines = 0x200,
305 .icache_assoc = 1,
306 .ecache_line_size = 0x20,
307 .ecache_lines = 0x4000,
308 .ecache_assoc = 1,
309 .mmu_nctx = 0x100,
310 .initfn = mb86904_init,
313 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
314 .name = "FMI,MB86907",
315 .psr_impl = 0,
316 .psr_vers = 5,
317 .impl = 0,
318 .vers = 5,
319 .dcache_line_size = 0x20,
320 .dcache_lines = 0x200,
321 .dcache_assoc = 1,
322 .icache_line_size = 0x20,
323 .icache_lines = 0x200,
324 .icache_assoc = 1,
325 .ecache_line_size = 0x20,
326 .ecache_lines = 0x4000,
327 .ecache_assoc = 1,
328 .mmu_nctx = 0x100,
329 .initfn = mb86904_init,
332 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
333 .name = "LSI,L64811",
334 .initfn = bad_cpu_init,
337 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
338 .name = "CY,CY7C601",
339 .psr_impl = 1,
340 .psr_vers = 1,
341 .impl = 1,
342 .vers = 1,
343 .mmu_nctx = 0x10,
344 .initfn = bad_cpu_init,
347 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
348 .name = "CY,CY7C611",
349 .initfn = bad_cpu_init,
352 .iu_version = 0x40000000,
353 .name = "TI,TMS390Z55",
354 .psr_impl = 4,
355 .psr_vers = 0,
356 .impl = 0,
357 .vers = 4,
358 .dcache_line_size = 0x20,
359 .dcache_lines = 0x80,
360 .dcache_assoc = 4,
361 .icache_line_size = 0x40,
362 .icache_lines = 0x40,
363 .icache_assoc = 5,
364 .ecache_line_size = 0x20,
365 .ecache_lines = 0x8000,
366 .ecache_assoc = 1,
367 .mmu_nctx = 0x10000,
368 .initfn = tms390z55_init,
371 .iu_version = 0x41000000,
372 .name = "TI,TMS390S10",
373 .psr_impl = 4,
374 .psr_vers = 1,
375 .impl = 4,
376 .vers = 1,
377 .dcache_line_size = 0x10,
378 .dcache_lines = 0x80,
379 .dcache_assoc = 4,
380 .icache_line_size = 0x20,
381 .icache_lines = 0x80,
382 .icache_assoc = 5,
383 .ecache_line_size = 0x20,
384 .ecache_lines = 0x8000,
385 .ecache_assoc = 1,
386 .mmu_nctx = 0x10000,
387 .initfn = tms390z55_init,
390 .iu_version = 0x42000000,
391 .name = "TI,TMS390S10",
392 .psr_impl = 4,
393 .psr_vers = 2,
394 .impl = 4,
395 .vers = 2,
396 .dcache_line_size = 0x10,
397 .dcache_lines = 0x80,
398 .dcache_assoc = 4,
399 .icache_line_size = 0x20,
400 .icache_lines = 0x80,
401 .icache_assoc = 5,
402 .ecache_line_size = 0x20,
403 .ecache_lines = 0x8000,
404 .ecache_assoc = 1,
405 .mmu_nctx = 0x10000,
406 .initfn = tms390z55_init,
409 .iu_version = 0x43000000,
410 .name = "TI,TMS390S10",
411 .psr_impl = 4,
412 .psr_vers = 3,
413 .impl = 4,
414 .vers = 3,
415 .dcache_line_size = 0x10,
416 .dcache_lines = 0x80,
417 .dcache_assoc = 4,
418 .icache_line_size = 0x20,
419 .icache_lines = 0x80,
420 .icache_assoc = 5,
421 .ecache_line_size = 0x20,
422 .ecache_lines = 0x8000,
423 .ecache_assoc = 1,
424 .mmu_nctx = 0x10000,
425 .initfn = tms390z55_init,
428 .iu_version = 0x44000000,
429 .name = "TI,TMS390S10",
430 .psr_impl = 4,
431 .psr_vers = 4,
432 .impl = 4,
433 .vers = 4,
434 .dcache_line_size = 0x10,
435 .dcache_lines = 0x80,
436 .dcache_assoc = 4,
437 .icache_line_size = 0x20,
438 .icache_lines = 0x80,
439 .icache_assoc = 5,
440 .ecache_line_size = 0x20,
441 .ecache_lines = 0x8000,
442 .ecache_assoc = 1,
443 .mmu_nctx = 0x10000,
444 .initfn = tms390z55_init,
447 .iu_version = 0x1e000000,
448 .name = "Ross,RT625",
449 .psr_impl = 1,
450 .psr_vers = 14,
451 .impl = 1,
452 .vers = 7,
453 .dcache_line_size = 0x20,
454 .dcache_lines = 0x80,
455 .dcache_assoc = 4,
456 .icache_line_size = 0x40,
457 .icache_lines = 0x40,
458 .icache_assoc = 5,
459 .ecache_line_size = 0x20,
460 .ecache_lines = 0x8000,
461 .ecache_assoc = 1,
462 .mmu_nctx = 0x10000,
463 .initfn = rt625_init,
466 .iu_version = 0x1f000000,
467 .name = "Ross,RT620",
468 .psr_impl = 1,
469 .psr_vers = 15,
470 .impl = 1,
471 .vers = 7,
472 .dcache_line_size = 0x20,
473 .dcache_lines = 0x80,
474 .dcache_assoc = 4,
475 .icache_line_size = 0x40,
476 .icache_lines = 0x40,
477 .icache_assoc = 5,
478 .ecache_line_size = 0x20,
479 .ecache_lines = 0x8000,
480 .ecache_assoc = 1,
481 .mmu_nctx = 0x10000,
482 .initfn = rt625_init,
485 .iu_version = 0x20000000,
486 .name = "BIT,B5010",
487 .initfn = bad_cpu_init,
490 .iu_version = 0x50000000,
491 .name = "MC,MN10501",
492 .initfn = bad_cpu_init,
495 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
496 .name = "Weitek,W8601",
497 .initfn = bad_cpu_init,
500 .iu_version = 0xf2000000,
501 .name = "GR,LEON2",
502 .initfn = bad_cpu_init,
505 .iu_version = 0xf3000000,
506 .name = "GR,LEON3",
507 .initfn = bad_cpu_init,
511 static const struct cpudef *
512 id_cpu(void)
514 unsigned long iu_version;
515 unsigned int i;
517 asm("rd %%psr, %0\n"
518 : "=r"(iu_version) :);
519 iu_version &= 0xff000000;
521 for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) {
522 if (iu_version == sparc_defs[i].iu_version)
523 return &sparc_defs[i];
525 printk("Unknown cpu (psr %lx), freezing!\n", iu_version);
526 for (;;);
529 static void dummy_mach_init(uint64_t base)
533 static void
534 ss5_init(uint64_t base)
536 ob_new_obio_device("slavioconfig", NULL);
538 ob_reg(base, SLAVIO_SCONFIG, SCONFIG_REGS, 0);
540 fword("finish-device");
543 struct machdef {
544 uint16_t machine_id;
545 const char *banner_name;
546 const char *model;
547 const char *name;
548 int mid_offset;
549 void (*initfn)(uint64_t base);
552 static const struct machdef sun4m_defs[] = {
554 .machine_id = 32,
555 .banner_name = "SPARCstation 5",
556 .model = "SUNW,501-3059",
557 .name = "SUNW,SPARCstation-5",
558 .mid_offset = 0,
559 .initfn = ss5_init,
562 .machine_id = 33,
563 .banner_name = "SPARCstation Voyager",
564 .model = "SUNW,501-2581",
565 .name = "SUNW,SPARCstation-Voyager",
566 .mid_offset = 0,
567 .initfn = dummy_mach_init,
570 .machine_id = 34,
571 .banner_name = "SPARCstation LX",
572 .model = "SUNW,501-2031",
573 .name = "SUNW,SPARCstation-LX",
574 .mid_offset = 0,
575 .initfn = dummy_mach_init,
578 .machine_id = 35,
579 .banner_name = "SPARCstation 4",
580 .model = "SUNW,501-2572",
581 .name = "SUNW,SPARCstation-4",
582 .mid_offset = 0,
583 .initfn = ss5_init,
586 .machine_id = 36,
587 .banner_name = "SPARCstation Classic",
588 .model = "SUNW,501-2326",
589 .name = "SUNW,SPARCstation-Classic",
590 .mid_offset = 0,
591 .initfn = dummy_mach_init,
594 .machine_id = 37,
595 .banner_name = "Tadpole S3 GX",
596 .model = "S3",
597 .name = "Tadpole_S3GX",
598 .mid_offset = 0,
599 .initfn = ss5_init,
602 .machine_id = 64,
603 .banner_name = "SPARCstation 10 (1 X 390Z55)",
604 .model = "SUNW,S10,501-2365",
605 .name = "SUNW,SPARCstation-10",
606 .mid_offset = 8,
607 .initfn = ob_eccmemctl_init,
610 .machine_id = 65,
611 .banner_name = "SPARCstation 20 (1 X 390Z55)",
612 .model = "SUNW,S20,501-2324",
613 .name = "SUNW,SPARCstation-20",
614 .mid_offset = 8,
615 .initfn = ob_eccmemctl_init,
618 .machine_id = 66,
619 .banner_name = "SPARCsystem 600(1 X 390Z55)",
620 .model = NULL,
621 .name = "SUNW,SPARCsystem-600",
622 .mid_offset = 8,
623 .initfn = ob_eccmemctl_init,
627 static const struct machdef *
628 id_machine(uint16_t machine_id)
630 unsigned int i;
632 for (i = 0; i < sizeof(sun4m_defs)/sizeof(struct machdef); i++) {
633 if (machine_id == sun4m_defs[i].machine_id)
634 return &sun4m_defs[i];
636 printk("Unknown machine (ID %d), freezing!\n", machine_id);
637 for (;;);
640 static uint8_t qemu_uuid[16];
642 static void
643 ob_nvram_init(uint64_t base, uint64_t offset)
645 const char *stdin, *stdout;
646 unsigned int i;
647 char nographic;
648 uint16_t machine_id;
649 const struct cpudef *cpu;
650 const struct machdef *mach;
651 char buf[256];
652 uint32_t temp;
653 phandle_t chosen;
655 ob_new_obio_device("eeprom", NULL);
657 nvram = (unsigned char *)ob_reg(base, offset, NVRAM_SIZE, 1);
659 PUSH((unsigned long)nvram);
660 fword("encode-int");
661 push_str("address");
662 fword("property");
664 push_str("mk48t08");
665 fword("model");
667 fword("finish-device");
669 fw_cfg_init();
671 fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
672 buf[4] = '\0';
674 printk("Configuration device id %s", buf);
676 temp = fw_cfg_read_i32(FW_CFG_ID);
677 machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
679 printk(" version %d machine id %d\n", temp, machine_id);
681 if (temp != 1) {
682 printk("Incompatible configuration device version, freezing\n");
683 for(;;);
686 fw_cfg_read(FW_CFG_NOGRAPHIC, &nographic, 1);
687 graphic_depth = fw_cfg_read_i16(FW_CFG_SUN4M_DEPTH);
689 // Add /uuid
690 fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16);
692 printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
693 qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
694 qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
695 qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
696 qemu_uuid[15]);
698 push_str("/");
699 fword("find-device");
701 PUSH((long)&qemu_uuid);
702 PUSH(16);
703 fword("encode-bytes");
704 push_str("uuid");
705 fword("property");
707 // Add /idprom
708 push_str("/");
709 fword("find-device");
711 PUSH((long)&nvram[NVRAM_IDPROM]);
712 PUSH(32);
713 fword("encode-bytes");
714 push_str("idprom");
715 fword("property");
717 mach = id_machine(machine_id);
719 push_str(mach->banner_name);
720 fword("encode-string");
721 push_str("banner-name");
722 fword("property");
724 if (mach->model) {
725 push_str(mach->model);
726 fword("encode-string");
727 push_str("model");
728 fword("property");
730 push_str(mach->name);
731 fword("encode-string");
732 push_str("name");
733 fword("property");
735 mach->initfn(base);
737 // Add cpus
738 temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
740 printk("CPUs: %x", temp);
741 cpu = id_cpu();
742 printk(" x %s\n", cpu->name);
743 for (i = 0; i < temp; i++) {
744 push_str("/");
745 fword("find-device");
747 fword("new-device");
749 push_str(cpu->name);
750 fword("device-name");
752 push_str("cpu");
753 fword("device-type");
755 PUSH(cpu->psr_impl);
756 fword("encode-int");
757 push_str("psr-implementation");
758 fword("property");
760 PUSH(cpu->psr_vers);
761 fword("encode-int");
762 push_str("psr-version");
763 fword("property");
765 PUSH(cpu->impl);
766 fword("encode-int");
767 push_str("implementation");
768 fword("property");
770 PUSH(cpu->vers);
771 fword("encode-int");
772 push_str("version");
773 fword("property");
775 PUSH(4096);
776 fword("encode-int");
777 push_str("page-size");
778 fword("property");
780 PUSH(cpu->dcache_line_size);
781 fword("encode-int");
782 push_str("dcache-line-size");
783 fword("property");
785 PUSH(cpu->dcache_lines);
786 fword("encode-int");
787 push_str("dcache-nlines");
788 fword("property");
790 PUSH(cpu->dcache_assoc);
791 fword("encode-int");
792 push_str("dcache-associativity");
793 fword("property");
795 PUSH(cpu->icache_line_size);
796 fword("encode-int");
797 push_str("icache-line-size");
798 fword("property");
800 PUSH(cpu->icache_lines);
801 fword("encode-int");
802 push_str("icache-nlines");
803 fword("property");
805 PUSH(cpu->icache_assoc);
806 fword("encode-int");
807 push_str("icache-associativity");
808 fword("property");
810 PUSH(cpu->ecache_line_size);
811 fword("encode-int");
812 push_str("ecache-line-size");
813 fword("property");
815 PUSH(cpu->ecache_lines);
816 fword("encode-int");
817 push_str("ecache-nlines");
818 fword("property");
820 PUSH(cpu->ecache_assoc);
821 fword("encode-int");
822 push_str("ecache-associativity");
823 fword("property");
825 PUSH(2);
826 fword("encode-int");
827 push_str("ncaches");
828 fword("property");
830 PUSH(cpu->mmu_nctx);
831 fword("encode-int");
832 push_str("mmu-nctx");
833 fword("property");
835 PUSH(8);
836 fword("encode-int");
837 push_str("sparc-version");
838 fword("property");
840 push_str("");
841 fword("encode-string");
842 push_str("cache-coherence?");
843 fword("property");
845 PUSH(i + mach->mid_offset);
846 fword("encode-int");
847 push_str("mid");
848 fword("property");
850 cpu->initfn();
852 fword("finish-device");
855 if (nographic) {
856 obp_stdin = PROMDEV_TTYA;
857 obp_stdout = PROMDEV_TTYA;
858 stdin = "ttya";
859 stdout = "ttya";
860 } else {
861 obp_stdin = PROMDEV_KBD;
862 obp_stdout = PROMDEV_SCREEN;
863 stdin = "keyboard";
864 stdout = "screen";
867 push_str("/");
868 fword("find-device");
870 push_str(stdin);
871 fword("pathres-resolve-aliases");
872 fword("encode-string");
873 push_str("stdin-path");
874 fword("property");
876 push_str(stdout);
877 fword("pathres-resolve-aliases");
878 fword("encode-string");
879 push_str("stdout-path");
880 fword("property");
882 chosen = find_dev("/chosen");
883 push_str(stdin);
884 fword("open-dev");
885 set_int_property(chosen, "stdin", POP());
887 chosen = find_dev("/chosen");
888 push_str(stdout);
889 fword("open-dev");
890 set_int_property(chosen, "stdout", POP());
892 push_str(stdin);
893 push_str("input-device");
894 fword("$setenv");
896 push_str(stdout);
897 push_str("output-device");
898 fword("$setenv");
900 push_str(stdin);
901 fword("input");
903 obp_stdin_path = stdin;
904 obp_stdout_path = stdout;
907 static void
908 ob_fd_init(uint64_t base, uint64_t offset, int intr)
910 unsigned long addr;
912 ob_new_obio_device("SUNW,fdtwo", "block");
914 addr = ob_reg(base, offset, FD_REGS, 1);
916 ob_intr(intr);
918 fword("is-deblocker");
920 ob_floppy_init("/obio", "SUNW,fdtwo", 0, addr);
922 fword("finish-device");
925 static void
926 ob_auxio_init(uint64_t base, uint64_t offset)
928 ob_new_obio_device("auxio", NULL);
930 ob_reg(base, offset, AUXIO_REGS, 0);
932 fword("finish-device");
935 volatile unsigned char *power_reg;
936 volatile unsigned int *reset_reg;
938 static void
939 sparc32_reset_all(void)
941 *reset_reg = 1;
944 // AUX 2 (Software Powerdown Control) and reset
945 static void
946 ob_aux2_reset_init(uint64_t base, uint64_t offset, int intr)
948 ob_new_obio_device("power", NULL);
950 power_reg = (void *)ob_reg(base, offset, AUXIO2_REGS, 1);
952 // Not in device tree
953 reset_reg = map_io(base + (uint64_t)SLAVIO_RESET, RESET_REGS);
955 bind_func("sparc32-reset-all", sparc32_reset_all);
956 push_str("' sparc32-reset-all to reset-all");
957 fword("eval");
959 ob_intr(intr);
961 fword("finish-device");
964 volatile struct sun4m_timer_regs *counter_regs;
966 static void
967 ob_counter_init(uint64_t base, unsigned long offset)
969 int i;
971 ob_new_obio_device("counter", NULL);
973 for (i = 0; i < SUN4M_NCPU; i++) {
974 PUSH(0);
975 fword("encode-int");
976 if (i != 0) fword("encode+");
977 PUSH(offset + (i * PAGE_SIZE));
978 fword("encode-int");
979 fword("encode+");
980 PUSH(COUNTER_REGS);
981 fword("encode-int");
982 fword("encode+");
985 PUSH(0);
986 fword("encode-int");
987 fword("encode+");
988 PUSH(offset + 0x10000);
989 fword("encode-int");
990 fword("encode+");
991 PUSH(COUNTER_REGS);
992 fword("encode-int");
993 fword("encode+");
995 push_str("reg");
996 fword("property");
999 counter_regs = map_io(base + (uint64_t)offset, sizeof(*counter_regs));
1000 counter_regs->cfg = 0xffffffff;
1001 counter_regs->l10_timer_limit = (((1000000/100) + 1) << 10);
1002 counter_regs->cpu_timers[0].l14_timer_limit = 0;
1003 counter_regs->cpu_timers[0].cntrl = 1;
1005 for (i = 0; i < SUN4M_NCPU; i++) {
1006 PUSH((unsigned long)&counter_regs->cpu_timers[i]);
1007 fword("encode-int");
1008 if (i != 0)
1009 fword("encode+");
1011 PUSH((unsigned long)&counter_regs->l10_timer_limit);
1012 fword("encode-int");
1013 fword("encode+");
1014 push_str("address");
1015 fword("property");
1017 fword("finish-device");
1020 static volatile struct sun4m_intregs *intregs;
1022 static void
1023 ob_interrupt_init(uint64_t base, unsigned long offset)
1025 int i;
1027 ob_new_obio_device("interrupt", NULL);
1029 for (i = 0; i < SUN4M_NCPU; i++) {
1030 PUSH(0);
1031 fword("encode-int");
1032 if (i != 0) fword("encode+");
1033 PUSH(offset + (i * PAGE_SIZE));
1034 fword("encode-int");
1035 fword("encode+");
1036 PUSH(INTERRUPT_REGS);
1037 fword("encode-int");
1038 fword("encode+");
1041 PUSH(0);
1042 fword("encode-int");
1043 fword("encode+");
1044 PUSH(offset + 0x10000);
1045 fword("encode-int");
1046 fword("encode+");
1047 PUSH(INTERRUPT_REGS);
1048 fword("encode-int");
1049 fword("encode+");
1051 push_str("reg");
1052 fword("property");
1054 intregs = map_io(base | (uint64_t)offset, sizeof(*intregs));
1055 intregs->clear = ~SUN4M_INT_MASKALL;
1056 intregs->cpu_intregs[0].clear = ~0x17fff;
1058 for (i = 0; i < SUN4M_NCPU; i++) {
1059 PUSH((unsigned long)&intregs->cpu_intregs[i]);
1060 fword("encode-int");
1061 if (i != 0)
1062 fword("encode+");
1064 PUSH((unsigned long)&intregs->tbt);
1065 fword("encode-int");
1066 fword("encode+");
1067 push_str("address");
1068 fword("property");
1070 fword("finish-device");
1073 /* SMP CPU boot structure */
1074 struct smp_cfg {
1075 uint32_t smp_ctx;
1076 uint32_t smp_ctxtbl;
1077 uint32_t smp_entry;
1078 uint32_t valid;
1081 static struct smp_cfg *smp_header;
1084 start_cpu(unsigned int pc, unsigned int context_ptr, unsigned int context, int cpu)
1086 if (!cpu)
1087 return -1;
1089 cpu &= 7;
1091 smp_header->smp_entry = pc;
1092 smp_header->smp_ctxtbl = context_ptr;
1093 smp_header->smp_ctx = context;
1094 smp_header->valid = cpu;
1096 intregs->cpu_intregs[cpu].set = SUN4M_SOFT_INT(14);
1098 return 0;
1101 static void
1102 ob_smp_init(void)
1104 unsigned long mem_size;
1106 // See arch/sparc32/entry.S for memory layout
1107 mem_size = fw_cfg_read_i32(FW_CFG_RAM_SIZE);
1108 smp_header = (struct smp_cfg *)map_io((uint64_t)(mem_size - 0x100),
1109 sizeof(struct smp_cfg));
1112 static void
1113 ob_obio_open(__attribute__((unused))int *idx)
1115 int ret=1;
1116 RET ( -ret );
1119 static void
1120 ob_obio_close(__attribute__((unused))int *idx)
1122 selfword("close-deblocker");
1125 static void
1126 ob_obio_initialize(__attribute__((unused))int *idx)
1128 push_str("/");
1129 fword("find-device");
1130 fword("new-device");
1132 push_str("obio");
1133 fword("device-name");
1135 push_str("hierarchical");
1136 fword("device-type");
1138 PUSH(2);
1139 fword("encode-int");
1140 push_str("#address-cells");
1141 fword("property");
1143 PUSH(1);
1144 fword("encode-int");
1145 push_str("#size-cells");
1146 fword("property");
1148 fword("finish-device");
1151 static void
1152 ob_set_obio_ranges(uint64_t base)
1154 push_str("/obio");
1155 fword("find-device");
1156 PUSH(0);
1157 fword("encode-int");
1158 PUSH(0);
1159 fword("encode-int");
1160 fword("encode+");
1161 PUSH(base >> 32);
1162 fword("encode-int");
1163 fword("encode+");
1164 PUSH(base & 0xffffffff);
1165 fword("encode-int");
1166 fword("encode+");
1167 PUSH(SLAVIO_SIZE);
1168 fword("encode-int");
1169 fword("encode+");
1170 push_str("ranges");
1171 fword("property");
1174 static void
1175 ob_obio_decodeunit(__attribute__((unused)) int *idx)
1177 fword("decode-unit-sbus");
1181 static void
1182 ob_obio_encodeunit(__attribute__((unused)) int *idx)
1184 fword("encode-unit-sbus");
1187 NODE_METHODS(ob_obio) = {
1188 { NULL, ob_obio_initialize },
1189 { "open", ob_obio_open },
1190 { "close", ob_obio_close },
1191 { "encode-unit", ob_obio_encodeunit },
1192 { "decode-unit", ob_obio_decodeunit },
1197 ob_obio_init(uint64_t slavio_base, unsigned long fd_offset,
1198 unsigned long counter_offset, unsigned long intr_offset,
1199 unsigned long aux1_offset, unsigned long aux2_offset)
1202 // All devices were integrated to NCR89C105, see
1203 // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
1205 //printk("Initializing OBIO devices...\n");
1206 #if 0 // XXX
1207 REGISTER_NAMED_NODE(ob_obio, "/obio");
1208 device_end();
1209 #endif
1210 ob_set_obio_ranges(slavio_base);
1212 // Zilog Z8530 serial ports, see http://www.zilog.com
1213 // Must be before zs@0,0 or Linux won't boot
1214 ob_zs_init(slavio_base, SLAVIO_ZS1, ZS_INTR, 0, 0);
1216 ob_zs_init(slavio_base, SLAVIO_ZS, ZS_INTR, 1, 1);
1218 // M48T08 NVRAM, see http://www.st.com
1219 ob_nvram_init(slavio_base, SLAVIO_NVRAM);
1221 // 82078 FDC
1222 if (fd_offset != (unsigned long) -1)
1223 ob_fd_init(slavio_base, fd_offset, FD_INTR);
1225 ob_auxio_init(slavio_base, aux1_offset);
1227 if (aux2_offset != (unsigned long) -1)
1228 ob_aux2_reset_init(slavio_base, aux2_offset, AUXIO2_INTR);
1230 ob_counter_init(slavio_base, counter_offset);
1232 ob_interrupt_init(slavio_base, intr_offset);
1234 ob_smp_init();
1236 return 0;