1 /* $NetBSD: machdep.c,v 1.25 2009/03/14 21:04:09 dsl Exp $ */
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.25 2009/03/14 21:04:09 dsl Exp $");
37 #include "opt_marvell.h"
38 #include "opt_modular.h"
39 #include "opt_ev64260.h"
40 #include "opt_compat_netbsd.h"
43 #include "opt_ccitt.h"
46 #include "opt_ipkdb.h"
48 #include <sys/param.h>
50 #include <sys/device.h>
51 #include <sys/kernel.h>
52 #include <sys/malloc.h>
53 #include <sys/mount.h>
54 #include <sys/msgbuf.h>
56 #include <sys/reboot.h>
57 #include <sys/extent.h>
58 #include <sys/syslog.h>
59 #include <sys/systm.h>
60 #include <sys/termios.h>
61 #include <sys/ksyms.h>
64 #include <uvm/uvm_extern.h>
66 #include <net/netisr.h>
68 #include <machine/bus.h>
69 #include <machine/db_machdep.h>
70 #include <machine/intr.h>
71 #include <machine/pmap.h>
72 #include <machine/powerpc.h>
73 #include <machine/trap.h>
75 #include <powerpc/oea/bat.h>
76 #include <powerpc/marvell/watchdog.h>
78 #include <ddb/db_extern.h>
84 #include <dev/ic/mc6845reg.h>
85 #include <dev/ic/pcdisplayvar.h>
86 #include <dev/ic/vgareg.h>
87 #include <dev/ic/vgavar.h>
92 void isa_intr_init(void);
97 #include <dev/ic/comreg.h>
98 #include <dev/ic/comvar.h>
101 #include <dev/marvell/gtreg.h>
102 #include <dev/marvell/gtvar.h>
103 #include <dev/marvell/gtethreg.h>
107 #include <dev/marvell/gtsdmareg.h>
108 #include <dev/marvell/gtmpscreg.h>
109 #include <dev/marvell/gtmpscvar.h>
115 * Global variables used here and there
117 #define PMONMEMREGIONS 32
118 struct mem_region physmemr
[PMONMEMREGIONS
], availmemr
[PMONMEMREGIONS
];
122 void initppc(u_int
, u_int
, u_int
, void *); /* Called from locore */
125 void gt_bus_space_init(void);
126 void gt_find_memory(bus_space_tag_t
, bus_space_handle_t
, paddr_t
);
127 void gt_halt(bus_space_tag_t
, bus_space_handle_t
);
128 void return_to_dink(int);
130 void kcomcnputs(dev_t
, const char *);
132 struct powerpc_bus_space gt_pci0_mem_bs_tag
= {
133 _BUS_SPACE_LITTLE_ENDIAN
|_BUS_SPACE_MEM_TYPE
,
134 0x00000000, 0x00000000, 0x00000000,
136 struct powerpc_bus_space gt_pci0_io_bs_tag
= {
137 _BUS_SPACE_LITTLE_ENDIAN
|_BUS_SPACE_IO_TYPE
,
138 0x00000000, 0x00000000, 0x00000000,
140 struct powerpc_bus_space gt_pci1_mem_bs_tag
= {
141 _BUS_SPACE_LITTLE_ENDIAN
|_BUS_SPACE_MEM_TYPE
,
142 0x00000000, 0x00000000, 0x00000000,
144 struct powerpc_bus_space gt_pci1_io_bs_tag
= {
145 _BUS_SPACE_LITTLE_ENDIAN
|_BUS_SPACE_IO_TYPE
,
146 0x00000000, 0x00000000, 0x00000000,
148 struct powerpc_bus_space gt_obio0_bs_tag
= {
149 _BUS_SPACE_BIG_ENDIAN
|_BUS_SPACE_MEM_TYPE
|OBIO0_STRIDE
,
150 0x00000000, 0x00000000, 0x00000000,
152 struct powerpc_bus_space gt_obio1_bs_tag
= {
153 _BUS_SPACE_BIG_ENDIAN
|_BUS_SPACE_MEM_TYPE
|OBIO1_STRIDE
,
154 0x00000000, 0x00000000, 0x00000000,
156 struct powerpc_bus_space gt_obio2_bs_tag
= {
157 _BUS_SPACE_BIG_ENDIAN
|_BUS_SPACE_MEM_TYPE
|OBIO2_STRIDE
,
158 0x00000000, 0x00000000, 0x00000000,
160 struct powerpc_bus_space gt_obio3_bs_tag
= {
161 _BUS_SPACE_BIG_ENDIAN
|_BUS_SPACE_MEM_TYPE
|OBIO3_STRIDE
,
162 0x00000000, 0x00000000, 0x00000000,
164 struct powerpc_bus_space gt_bootcs_bs_tag
= {
165 _BUS_SPACE_BIG_ENDIAN
|_BUS_SPACE_MEM_TYPE
,
166 0x00000000, 0x00000000, 0x00000000,
168 struct powerpc_bus_space gt_mem_bs_tag
= {
169 _BUS_SPACE_LITTLE_ENDIAN
|_BUS_SPACE_MEM_TYPE
,
170 GT_BASE
, 0x00000000, 0x00010000,
173 bus_space_handle_t gt_memh
;
175 struct powerpc_bus_space
*obio_bs_tags
[5] = {
176 >_obio0_bs_tag
, >_obio1_bs_tag
, >_obio2_bs_tag
,
177 >_obio3_bs_tag
, >_bootcs_bs_tag
180 static char ex_storage
[10][EXTENT_FIXED_STORAGE_SIZE(8)]
181 __attribute__((aligned(8)));
183 const struct gt_decode_info
{
184 bus_addr_t low_decode
;
185 bus_addr_t high_decode
;
187 { GT_SCS0_Low_Decode
, GT_SCS0_High_Decode
},
188 { GT_SCS1_Low_Decode
, GT_SCS1_High_Decode
},
189 { GT_SCS2_Low_Decode
, GT_SCS2_High_Decode
},
190 { GT_SCS3_Low_Decode
, GT_SCS3_High_Decode
},
191 { GT_CS0_Low_Decode
, GT_CS0_High_Decode
},
192 { GT_CS1_Low_Decode
, GT_CS1_High_Decode
},
193 { GT_CS2_Low_Decode
, GT_CS2_High_Decode
},
194 { GT_CS3_Low_Decode
, GT_CS3_High_Decode
},
195 { GT_BootCS_Low_Decode
, GT_BootCS_High_Decode
},
199 initppc(u_int startkernel
, u_int endkernel
, u_int args
, void *btinfo
)
201 oea_batinit(0xf0000000, BAT_BL_256M
);
202 oea_init((void (*)(void))ext_intr
);
207 gt_find_memory(>_mem_bs_tag
, gt_memh
, roundup(endkernel
, PAGE_SIZE
));
208 gt_halt(>_mem_bs_tag
, gt_memh
);
211 * Now that we known how much memory, reinit the bats.
213 oea_batinit(0xf0000000, BAT_BL_256M
);
227 * Initialize pmap module.
229 pmap_bootstrap(startkernel
, endkernel
);
231 #if NKSYMS || defined(DDB) || defined(MODULAR)
233 extern void *startsym
, *endsym
;
234 ksyms_addsyms_elf((int)((u_int
)endsym
- (u_int
)startsym
),
243 if (boothowto
& RB_KDB
)
249 mem_regions(struct mem_region
**mem
, struct mem_region
**avail
)
256 gt_record_memory(int j
, paddr_t start
, paddr_t end
, paddr_t endkernel
)
258 physmemr
[j
].start
= start
;
259 physmemr
[j
].size
= end
- start
;
260 if (start
< endkernel
)
262 availmemr
[j
].start
= start
;
263 availmemr
[j
].size
= end
- start
;
267 gt_find_memory(bus_space_tag_t memt
, bus_space_handle_t memh
,
270 paddr_t start
= ~0, end
= 0;
271 int i
, j
= 0, first
= 1;
274 * Round kernel end to a page boundary.
276 for (i
= 0; i
< 4; i
++) {
277 paddr_t nstart
, nend
;
278 nstart
= GT_LowAddr_GET(bus_space_read_4(>_mem_bs_tag
,
279 gt_memh
, decode_regs
[i
].low_decode
));
280 nend
= GT_HighAddr_GET(bus_space_read_4(>_mem_bs_tag
,
281 gt_memh
, decode_regs
[i
].high_decode
)) + 1;
286 * First entry? Just remember it.
291 } else if (nstart
== end
) {
293 * Contiguous? Just update the end.
298 * Disjoint? record it.
300 gt_record_memory(j
, start
, end
, endkernel
);
306 gt_record_memory(j
, start
, end
, endkernel
);
310 * Machine dependent startup code.
320 * Now that we have VM, malloc()s are OK in bus_space.
322 bus_space_mallocok();
325 * Now allow hardware interrupts.
328 __asm
volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0"
335 * Initialize system console.
341 /* PMON using MPSC0 @ 9600 */
342 gtmpsccnattach(>_mem_bs_tag
, gt_memh
, MPSC_CONSOLE
, 9600,
343 (TTYDEF_CFLAG
& ~(CSIZE
| CSTOPB
| PARENB
)) | CS8
);
345 /* PPCBOOT using COM1 @ 57600 */
346 comcnattach(>_obio2_bs_tag
, 0, 57600,
347 COM_FREQ
*2, COM_TYPE_NORMAL
,
348 (TTYDEF_CFLAG
& ~(CSIZE
| CSTOPB
| PARENB
)) | CS8
);
358 log(LOG_ERR
, "stray interrupt %d\n", irq
);
362 * Halt or reboot the machine after syncing/dumping according to howto.
365 cpu_reboot(int howto
, char *what
)
368 static char str
[256];
369 char *ap
= str
, *ap1
= ap
;
372 if (!cold
&& !(howto
& RB_NOSYNC
) && !syncing
) {
374 vfs_shutdown(); /* sync */
375 resettodr(); /* set wall clock */
378 if (howto
& RB_HALT
) {
380 pmf_system_shutdown(boothowto
);
381 printf("halted\n\n");
385 if (!cold
&& (howto
& RB_DUMP
))
389 pmf_system_shutdown(boothowto
);
390 printf("rebooting\n\n");
392 if (strlen(what
) > sizeof str
- 5)
393 printf("boot string too large, ignored\n");
396 ap1
= ap
= str
+ strlen(str
);
401 if (howto
& RB_SINGLE
)
410 void mvpppc_reboot(void);
422 return spllower(ipl
);
426 gt_halt(bus_space_tag_t memt
, bus_space_handle_t memh
)
432 * Shut down the MPSC ports
434 for (i
= 0; i
< 2; i
++) {
435 bus_space_write_4(memt
, memh
,
436 SDMA_U_SDCM(i
), SDMA_SDCM_AR
|SDMA_SDCM_AT
);
438 data
= bus_space_read_4(memt
, memh
,
440 if (((SDMA_SDCM_AR
|SDMA_SDCM_AT
) & data
) == 0)
446 * Shut down the Ethernets
448 for (i
= 0; i
< 3; i
++) {
449 bus_space_write_4(memt
, memh
,
450 ETH_ESDCMR(2), ETH_ESDCMR_AR
|ETH_ESDCMR_AT
);
452 data
= bus_space_read_4(memt
, memh
,
454 if (((ETH_ESDCMR_AR
|ETH_ESDCMR_AT
) & data
) == 0)
457 data
= bus_space_read_4(memt
, memh
, ETH_EPCR(i
));
458 data
&= ~ETH_EPCR_EN
;
459 bus_space_write_4(memt
, memh
, ETH_EPCR(i
), data
);
464 gtget_macaddr(struct gt_softc
*gt
, int macno
, char *enaddr
)
471 enaddr
[5] = 0x04 + macno
;
477 gt_bus_space_init(void)
479 bus_space_tag_t gt_memt
= >_mem_bs_tag
;
480 const struct gt_decode_info
*di
;
481 uint32_t datal
, datah
;
486 error
= bus_space_init(>_mem_bs_tag
, "gtmem",
487 ex_storage
[bs
], sizeof(ex_storage
[bs
]));
489 error
= bus_space_map(gt_memt
, 0, 0x10000, 0, >_memh
);
491 for (j
= 0, di
= &decode_regs
[4]; j
< 5; j
++, di
++) {
492 struct powerpc_bus_space
*memt
= obio_bs_tags
[j
];
493 datal
= bus_space_read_4(gt_memt
, gt_memh
, di
->low_decode
);
494 datah
= bus_space_read_4(gt_memt
, gt_memh
, di
->high_decode
);
496 if (GT_LowAddr_GET(datal
) >= GT_HighAddr_GET(datal
)) {
497 obio_bs_tags
[j
] = NULL
;
500 memt
->pbs_offset
= GT_LowAddr_GET(datal
);
501 memt
->pbs_limit
= GT_HighAddr_GET(datah
) + 1 -
504 error
= bus_space_init(memt
, "obio2",
505 ex_storage
[bs
], sizeof(ex_storage
[bs
]));
509 datal
= bus_space_read_4(gt_memt
, gt_memh
, GT_PCI0_Mem0_Low_Decode
);
510 datah
= bus_space_read_4(gt_memt
, gt_memh
, GT_PCI0_Mem0_High_Decode
);
511 #if defined(GT_PCI0_MEMBASE)
513 datal
|= (GT_PCI0_MEMBASE
>> 20);
514 bus_space_write_4(gt_memt
, gt_memh
, GT_PCI0_Mem0_Low_Decode
, datal
);
516 #if defined(GT_PCI0_MEMSIZE)
518 datah
|= (GT_PCI0_MEMSIZE
+ GT_LowAddr_GET(datal
) - 1) >> 20;
519 bus_space_write_4(gt_memt
, gt_memh
, GT_PCI0_Mem0_High_Decode
, datal
);
521 gt_pci0_mem_bs_tag
.pbs_base
= GT_LowAddr_GET(datal
);
522 gt_pci0_mem_bs_tag
.pbs_limit
= GT_HighAddr_GET(datah
) + 1;
524 error
= bus_space_init(>_pci0_mem_bs_tag
, "pci0-mem",
525 ex_storage
[bs
], sizeof(ex_storage
[bs
]));
529 * Make sure PCI0 Memory is BAT mapped.
531 if (GT_LowAddr_GET(datal
) < GT_HighAddr_GET(datal
))
532 oea_iobat_add(gt_pci0_mem_bs_tag
.pbs_base
& SEGMENT_MASK
, BAT_BL_256M
);
535 * Make sure that I/O space start at 0.
537 bus_space_write_4(gt_memt
, gt_memh
, GT_PCI1_IO_Remap
, 0);
539 datal
= bus_space_read_4(gt_memt
, gt_memh
, GT_PCI0_IO_Low_Decode
);
540 datah
= bus_space_read_4(gt_memt
, gt_memh
, GT_PCI0_IO_High_Decode
);
541 #if defined(GT_PCI0_IOBASE)
543 datal
|= (GT_PCI0_IOBASE
>> 20);
544 bus_space_write_4(gt_memt
, gt_memh
, GT_PCI0_IO_Low_Decode
, datal
);
546 #if defined(GT_PCI0_IOSIZE)
548 datah
|= (GT_PCI0_IOSIZE
+ GT_LowAddr_GET(datal
) - 1) >> 20;
549 bus_space_write_4(gt_memt
, gt_memh
, GT_PCI0_IO_High_Decode
, datal
);
551 gt_pci0_io_bs_tag
.pbs_offset
= GT_LowAddr_GET(datal
);
552 gt_pci0_io_bs_tag
.pbs_limit
= GT_HighAddr_GET(datah
) + 1 -
553 gt_pci0_io_bs_tag
.pbs_offset
;
555 error
= bus_space_init(>_pci0_io_bs_tag
, "pci0-ioport",
556 ex_storage
[bs
], sizeof(ex_storage
[bs
]));
560 error
= extent_alloc_region(gt_pci0_io_bs_tag
.pbs_extent
,
561 0x10000, 0x7F0000, EX_NOWAIT
);
563 panic("gt_bus_space_init: can't block out reserved "
564 "I/O space 0x10000-0x7fffff: error=%d\n", error
);
567 datal
= bus_space_read_4(gt_memt
, gt_memh
, GT_PCI1_Mem0_Low_Decode
);
568 datah
= bus_space_read_4(gt_memt
, gt_memh
, GT_PCI1_Mem0_High_Decode
);
569 #if defined(GT_PCI1_MEMBASE)
571 datal
|= (GT_PCI1_MEMBASE
>> 20);
572 bus_space_write_4(gt_memt
, gt_memh
, GT_PCI1_Mem0_Low_Decode
, datal
);
574 #if defined(GT_PCI1_MEMSIZE)
576 datah
|= (GT_PCI1_MEMSIZE
+ GT_LowAddr_GET(datal
) - 1) >> 20;
577 bus_space_write_4(gt_memt
, gt_memh
, GT_PCI1_Mem0_High_Decode
, datal
);
579 gt_pci1_mem_bs_tag
.pbs_base
= GT_LowAddr_GET(datal
);
580 gt_pci1_mem_bs_tag
.pbs_limit
= GT_HighAddr_GET(datah
) + 1;
582 error
= bus_space_init(>_pci1_mem_bs_tag
, "pci1-mem",
583 ex_storage
[bs
], sizeof(ex_storage
[bs
]));
587 * Make sure PCI1 Memory is BAT mapped.
589 if (GT_LowAddr_GET(datal
) < GT_HighAddr_GET(datal
))
590 oea_iobat_add(gt_pci1_mem_bs_tag
.pbs_base
& SEGMENT_MASK
, BAT_BL_256M
);
593 * Make sure that I/O space start at 0.
595 bus_space_write_4(gt_memt
, gt_memh
, GT_PCI1_IO_Remap
, 0);
597 datal
= bus_space_read_4(gt_memt
, gt_memh
, GT_PCI1_IO_Low_Decode
);
598 datah
= bus_space_read_4(gt_memt
, gt_memh
, GT_PCI1_IO_High_Decode
);
599 #if defined(GT_PCI1_IOBASE)
601 datal
|= (GT_PCI1_IOBASE
>> 20);
602 bus_space_write_4(gt_memt
, gt_memh
, GT_PCI1_IO_Low_Decode
, datal
);
604 #if defined(GT_PCI1_IOSIZE)
606 datah
|= (GT_PCI1_IOSIZE
+ GT_LowAddr_GET(datal
) - 1) >> 20;
607 bus_space_write_4(gt_memt
, gt_memh
, GT_PCI1_IO_High_Decode
, datal
);
609 gt_pci1_io_bs_tag
.pbs_offset
= GT_LowAddr_GET(datal
);
610 gt_pci1_io_bs_tag
.pbs_limit
= GT_HighAddr_GET(datah
) + 1 -
611 gt_pci1_io_bs_tag
.pbs_offset
;
613 error
= bus_space_init(>_pci1_io_bs_tag
, "pci1-ioport",
614 ex_storage
[bs
], sizeof(ex_storage
[bs
]));
618 error
= extent_alloc_region(gt_pci1_io_bs_tag
.pbs_extent
,
619 0x10000, 0x7F0000, EX_NOWAIT
);
621 panic("gt_bus_space_init: can't block out reserved "
622 "I/O space 0x10000-0x7fffff: error=%d\n", error
);