1 /* $NetBSD: machdep.c,v 1.28 2010/12/20 00:25:32 matt Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 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. 21 * 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. 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.28 2010/12/20 00:25:32 matt Exp $"); 36 37 #include "opt_marvell.h" 38 #include "opt_modular.h" 39 #include "opt_ev64260.h" 40 #include "opt_compat_netbsd.h" 41 #include "opt_ddb.h" 42 #include "opt_inet.h" 43 #include "opt_ccitt.h" 44 #include "opt_iso.h" 45 #include "opt_ns.h" 46 #include "opt_ipkdb.h" 47 48 #define _POWERPC_BUS_DMA_PRIVATE 49 50 #include <sys/param.h> 51 #include <sys/bus.h> 52 #include <sys/conf.h> 53 #include <sys/device.h> 54 #include <sys/extent.h> 55 #include <sys/kernel.h> 56 #include <sys/ksyms.h> 57 #include <sys/mount.h> 58 #include <sys/reboot.h> 59 #include <sys/systm.h> 60 #include <sys/termios.h> 61 #include <sys/vnode.h> 62 63 #include <uvm/uvm_extern.h> 64 65 #include <net/netisr.h> 66 67 #include <machine/db_machdep.h> 68 #include <machine/pmap.h> 69 #include <machine/powerpc.h> 70 71 #include <powerpc/oea/bat.h> 72 #include <powerpc/pic/picvar.h> 73 #include <powerpc/pio.h> 74 75 #include <ddb/db_extern.h> 76 77 #include <dev/cons.h> 78 79 #include "com.h" 80 #if (NCOM > 0) 81 #include <dev/ic/comreg.h> 82 #include <dev/ic/comvar.h> 83 #endif 84 85 #include <dev/marvell/gtreg.h> 86 #include <dev/marvell/gtvar.h> 87 88 #include "gtmpsc.h" 89 #if (NGTMPSC > 0) 90 #include <dev/marvell/gtbrgreg.h> 91 #include <dev/marvell/gtsdmareg.h> 92 #include <dev/marvell/gtmpscreg.h> 93 #include <dev/marvell/gtmpscvar.h> 94 #endif 95 96 #include "ksyms.h" 97 #include "locators.h" 98 99 100 /* 101 * Global variables used here and there 102 */ 103 #define PMONMEMREGIONS 32 104 struct mem_region physmemr[PMONMEMREGIONS], availmemr[PMONMEMREGIONS]; 105 106 void initppc(u_int, u_int, u_int, void *); /* Called from locore */ 107 static void gt_bus_space_init(void); 108 static inline void gt_record_memory(int, paddr_t, paddr_t, paddr_t); 109 static void gt_find_memory(paddr_t); 110 111 bus_addr_t gt_base = 0; 112 113 extern int primary_pic; 114 struct pic_ops *discovery_pic; 115 struct pic_ops *discovery_gpp_pic[4]; 116 117 118 struct powerpc_bus_space ev64260_pci0_mem_bs_tag = { 119 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 120 0x00000000, 0x00000000, 0x00000000, 121 }; 122 struct powerpc_bus_space ev64260_pci0_io_bs_tag = { 123 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE, 124 0x00000000, 0x00000000, 0x00000000, 125 }; 126 struct powerpc_bus_space ev64260_pci1_mem_bs_tag = { 127 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 128 0x00000000, 0x00000000, 0x00000000, 129 }; 130 struct powerpc_bus_space ev64260_pci1_io_bs_tag = { 131 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE, 132 0x00000000, 0x00000000, 0x00000000, 133 }; 134 struct powerpc_bus_space ev64260_obio0_bs_tag = { 135 _BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE|OBIO0_STRIDE, 136 0x00000000, 0x00000000, 0x00000000, 137 }; 138 struct powerpc_bus_space ev64260_obio1_bs_tag = { 139 _BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE|OBIO1_STRIDE, 140 0x00000000, 0x00000000, 0x00000000, 141 }; 142 struct powerpc_bus_space ev64260_obio2_bs_tag = { 143 _BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE|OBIO2_STRIDE, 144 0x00000000, 0x00000000, 0x00000000, 145 }; 146 struct powerpc_bus_space ev64260_obio3_bs_tag = { 147 _BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE|OBIO3_STRIDE, 148 0x00000000, 0x00000000, 0x00000000, 149 }; 150 struct powerpc_bus_space ev64260_bootcs_bs_tag = { 151 _BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE, 152 0x00000000, 0x00000000, 0x00000000, 153 }; 154 struct powerpc_bus_space ev64260_gt_bs_tag = { 155 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 156 0x00000000, 0x00000000, GT_SIZE, 157 }; 158 159 struct powerpc_bus_space *ev64260_obio_bs_tags[5] = { 160 &ev64260_obio0_bs_tag, &ev64260_obio1_bs_tag, &ev64260_obio2_bs_tag, 161 &ev64260_obio3_bs_tag, &ev64260_bootcs_bs_tag 162 }; 163 164 static char ex_storage[10][EXTENT_FIXED_STORAGE_SIZE(8)] 165 __attribute__((aligned(8))); 166 167 const struct gt_decode_info { 168 bus_addr_t low_decode; 169 bus_addr_t high_decode; 170 } decode_regs[] = { 171 { GT_SCS0_Low_Decode, GT_SCS0_High_Decode }, 172 { GT_SCS1_Low_Decode, GT_SCS1_High_Decode }, 173 { GT_SCS2_Low_Decode, GT_SCS2_High_Decode }, 174 { GT_SCS3_Low_Decode, GT_SCS3_High_Decode }, 175 { GT_CS0_Low_Decode, GT_CS0_High_Decode }, 176 { GT_CS1_Low_Decode, GT_CS1_High_Decode }, 177 { GT_CS2_Low_Decode, GT_CS2_High_Decode }, 178 { GT_CS3_Low_Decode, GT_CS3_High_Decode }, 179 { GT_BootCS_Low_Decode, GT_BootCS_High_Decode }, 180 }; 181 182 struct powerpc_bus_dma_tag ev64260_bus_dma_tag = { 183 0, /* _bounce_thresh */ 184 _bus_dmamap_create, 185 _bus_dmamap_destroy, 186 _bus_dmamap_load, 187 _bus_dmamap_load_mbuf, 188 _bus_dmamap_load_uio, 189 _bus_dmamap_load_raw, 190 _bus_dmamap_unload, 191 _bus_dmamap_sync, 192 _bus_dmamem_alloc, 193 _bus_dmamem_free, 194 _bus_dmamem_map, 195 _bus_dmamem_unmap, 196 _bus_dmamem_mmap, 197 }; 198 199 200 void 201 initppc(u_int startkernel, u_int endkernel, u_int args, void *btinfo) 202 { 203 extern struct cfdata cfdata[]; 204 cfdata_t cf = &cfdata[0]; 205 206 /* Get mapped address of gt(System Controller) */ 207 while (cf->cf_name != NULL) { 208 if (strcmp(cf->cf_name, "gt") == 0 && 209 *cf->cf_loc != MAINBUSCF_ADDR_DEFAULT) 210 break; 211 cf++; 212 } 213 if (cf->cf_name == NULL) 214 panic("where is gt?"); 215 gt_base = *cf->cf_loc; 216 217 ev64260_gt_bs_tag.pbs_offset = gt_base; 218 ev64260_gt_bs_tag.pbs_base = gt_base; 219 ev64260_gt_bs_tag.pbs_limit += gt_base; 220 oea_batinit(gt_base, BAT_BL_256M); 221 222 oea_init(NULL); 223 224 gt_bus_space_init(); 225 gt_find_memory(roundup(endkernel, PAGE_SIZE)); 226 227 consinit(); 228 229 /* 230 * Set the page size. 231 */ 232 uvm_setpagesize(); 233 234 /* 235 * Initialize pmap module. 236 */ 237 pmap_bootstrap(startkernel, endkernel); 238 239 #if NKSYMS || defined(DDB) || defined(MODULAR) 240 { 241 extern void *startsym, *endsym; 242 ksyms_addsyms_elf((int)((u_int)endsym - (u_int)startsym), 243 startsym, endsym); 244 } 245 #endif 246 #ifdef IPKDB 247 /* 248 * Now trap to IPKDB 249 */ 250 ipkdb_init(); 251 if (boothowto & RB_KDB) 252 ipkdb_connect(0); 253 #endif 254 } 255 256 /* 257 * Machine dependent startup code. 258 */ 259 void 260 cpu_startup(void) 261 { 262 register_t msr; 263 264 oea_startup(NULL); 265 266 pic_init(); 267 discovery_pic = setup_discovery_pic(); 268 primary_pic = 0; 269 discovery_gpp_pic[0] = setup_discovery_gpp_pic(discovery_pic, 0); 270 discovery_gpp_pic[1] = setup_discovery_gpp_pic(discovery_pic, 8); 271 discovery_gpp_pic[2] = setup_discovery_gpp_pic(discovery_pic, 16); 272 discovery_gpp_pic[3] = setup_discovery_gpp_pic(discovery_pic, 24); 273 /* 274 * GPP interrupts establishes later. 275 */ 276 277 oea_install_extint(pic_ext_intr); 278 279 /* 280 * Now that we have VM, malloc()s are OK in bus_space. 281 */ 282 bus_space_mallocok(); 283 284 /* 285 * Now allow hardware interrupts. 286 */ 287 splraise(-1); 288 __asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0" 289 : "=r"(msr) 290 : "K"(PSL_EE)); 291 } 292 293 /* 294 * consinit 295 * Initialize system console. 296 */ 297 void 298 consinit(void) 299 { 300 301 #ifdef MPSC_CONSOLE 302 /* PMON using MPSC0 @ 9600 */ 303 const int brg = GTMPSC_CRR_BRG0; 304 const int baud = 9600; 305 uint32_t cr; 306 307 #if 1 308 /* 309 * XXX HACK FIXME 310 * PMON output has not been flushed. give him a chance 311 */ 312 DELAY(100000); /* XXX */ 313 #endif 314 /* Setup MPSC Routing Registers */ 315 out32rb(gt_base + GTMPSC_MRR, GTMPSC_MRR_RES); 316 cr = in32rb(gt_base + GTMPSC_RCRR); 317 cr &= ~GTMPSC_CRR(MPSC_CONSOLE, GTMPSC_CRR_MASK); 318 cr |= GTMPSC_CRR(MPSC_CONSOLE, brg); 319 out32rb(gt_base + GTMPSC_RCRR, cr); 320 out32rb(gt_base + GTMPSC_TCRR, cr); 321 322 /* Setup Baud Rate Configuration Register of Baud Rate Generator */ 323 out32rb(gt_base + BRG_BCR(brg), 324 BRG_BCR_EN | GT_MPSC_CLOCK_SOURCE | compute_cdv(baud)); 325 326 gtmpsccnattach(&ev64260_gt_bs_tag, &ev64260_bus_dma_tag, gt_base, 327 MPSC_CONSOLE, brg, baud, 328 (TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8); 329 #else 330 /* PPCBOOT using COM1 @ 57600 */ 331 comcnattach(>_obio2_bs_tag, 0, 57600, 332 COM_FREQ*2, COM_TYPE_NORMAL, 333 (TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8); 334 #endif 335 } 336 337 /* 338 * Halt or reboot the machine after syncing/dumping according to howto. 339 */ 340 void 341 cpu_reboot(int howto, char *what) 342 { 343 static int syncing; 344 static char str[256]; 345 char *ap = str, *ap1 = ap; 346 347 boothowto = howto; 348 if (!cold && !(howto & RB_NOSYNC) && !syncing) { 349 syncing = 1; 350 vfs_shutdown(); /* sync */ 351 resettodr(); /* set wall clock */ 352 } 353 splhigh(); 354 if (howto & RB_HALT) { 355 doshutdownhooks(); 356 pmf_system_shutdown(boothowto); 357 printf("halted\n\n"); 358 cnhalt(); 359 while(1); 360 } 361 if (!cold && (howto & RB_DUMP)) 362 oea_dumpsys(); 363 doshutdownhooks(); 364 365 pmf_system_shutdown(boothowto); 366 printf("rebooting\n\n"); 367 if (what && *what) { 368 if (strlen(what) > sizeof str - 5) 369 printf("boot string too large, ignored\n"); 370 else { 371 strcpy(str, what); 372 ap1 = ap = str + strlen(str); 373 *ap++ = ' '; 374 } 375 } 376 *ap++ = '-'; 377 if (howto & RB_SINGLE) 378 *ap++ = 's'; 379 if (howto & RB_KDB) 380 *ap++ = 'd'; 381 *ap++ = 0; 382 if (ap[-2] == '-') 383 *ap1 = 0; 384 gt_watchdog_reset(); 385 /* NOTREACHED */ 386 while (1); 387 } 388 389 void 390 mem_regions(struct mem_region **mem, struct mem_region **avail) 391 { 392 393 *mem = physmemr; 394 *avail = availmemr; 395 } 396 397 static void 398 gt_bus_space_init(void) 399 { 400 const struct gt_decode_info *di; 401 uint32_t datal, datah; 402 int error, bs, i; 403 404 bs = 0; 405 error = bus_space_init(&ev64260_gt_bs_tag, "gt", 406 ex_storage[bs], sizeof(ex_storage[bs])); 407 bs++; 408 409 for (i = 0, di = &decode_regs[4]; i < 5; i++, di++) { 410 struct powerpc_bus_space *memt = ev64260_obio_bs_tags[i]; 411 412 datal = in32rb(gt_base + di->low_decode); 413 datah = in32rb(gt_base + di->high_decode); 414 415 if (GT_LowAddr_GET(datal) >= GT_HighAddr_GET(datal)) { 416 ev64260_obio_bs_tags[i] = NULL; 417 continue; 418 } 419 memt->pbs_offset = GT_LowAddr_GET(datal); 420 memt->pbs_limit = GT_HighAddr_GET(datah) + 1 - 421 memt->pbs_offset; 422 423 error = bus_space_init(memt, "obio2", 424 ex_storage[bs], sizeof(ex_storage[bs])); 425 bs++; 426 } 427 428 datal = in32rb(gt_base + GT_PCI0_Mem0_Low_Decode); 429 datah = in32rb(gt_base + GT_PCI0_Mem0_High_Decode); 430 #if defined(GT_PCI0_MEMBASE) 431 datal &= ~0xfff; 432 datal |= (GT_PCI0_MEMBASE >> 20); 433 out32rb(gt_base + GT_PCI0_Mem0_Low_Decode, datal); 434 #endif 435 #if defined(GT_PCI0_MEMSIZE) 436 datah &= ~0xfff; 437 datah |= (GT_PCI0_MEMSIZE + GT_LowAddr_GET(datal) - 1) >> 20; 438 out32rb(gt_base + GT_PCI0_Mem0_High_Decode, datal); 439 #endif 440 ev64260_pci0_mem_bs_tag.pbs_base = GT_LowAddr_GET(datal); 441 ev64260_pci0_mem_bs_tag.pbs_limit = GT_HighAddr_GET(datah) + 1; 442 443 error = bus_space_init(&ev64260_pci0_mem_bs_tag, "pci0-mem", 444 ex_storage[bs], sizeof(ex_storage[bs])); 445 bs++; 446 447 #if 1 /* XXXXXX */ 448 /* 449 * Make sure PCI0 Memory is BAT mapped. 450 */ 451 if (GT_LowAddr_GET(datal) < GT_HighAddr_GET(datal)) 452 oea_iobat_add(ev64260_pci0_mem_bs_tag.pbs_base & SEGMENT_MASK, 453 BAT_BL_256M); 454 #endif 455 456 /* 457 * Make sure that I/O space start at 0. 458 */ 459 out32rb(gt_base + GT_PCI1_IO_Remap, 0); 460 461 datal = in32rb(gt_base + GT_PCI0_IO_Low_Decode); 462 datah = in32rb(gt_base + GT_PCI0_IO_High_Decode); 463 #if defined(GT_PCI0_IOBASE) 464 datal &= ~0xfff; 465 datal |= (GT_PCI0_IOBASE >> 20); 466 out32rb(gt_base + GT_PCI0_IO_Low_Decode, datal); 467 #endif 468 #if defined(GT_PCI0_IOSIZE) 469 datah &= ~0xfff; 470 datah |= (GT_PCI0_IOSIZE + GT_LowAddr_GET(datal) - 1) >> 20; 471 out32rb(gt_base + GT_PCI0_IO_High_Decode, datal); 472 #endif 473 ev64260_pci0_io_bs_tag.pbs_offset = GT_LowAddr_GET(datal); 474 ev64260_pci0_io_bs_tag.pbs_limit = GT_HighAddr_GET(datah) + 1 - 475 ev64260_pci0_io_bs_tag.pbs_offset; 476 477 error = bus_space_init(&ev64260_pci0_io_bs_tag, "pci0-ioport", 478 ex_storage[bs], sizeof(ex_storage[bs])); 479 bs++; 480 481 datal = in32rb(gt_base + GT_PCI1_Mem0_Low_Decode); 482 datah = in32rb(gt_base + GT_PCI1_Mem0_High_Decode); 483 #if defined(GT_PCI1_MEMBASE) 484 datal &= ~0xfff; 485 datal |= (GT_PCI1_MEMBASE >> 20); 486 out32rb(gt_base + GT_PCI1_Mem0_Low_Decode, datal); 487 #endif 488 #if defined(GT_PCI1_MEMSIZE) 489 datah &= ~0xfff; 490 datah |= (GT_PCI1_MEMSIZE + GT_LowAddr_GET(datal) - 1) >> 20; 491 out32rb(gt_base + GT_PCI1_Mem0_High_Decode, datal); 492 #endif 493 ev64260_pci1_mem_bs_tag.pbs_base = GT_LowAddr_GET(datal); 494 ev64260_pci1_mem_bs_tag.pbs_limit = GT_HighAddr_GET(datah) + 1; 495 496 error = bus_space_init(&ev64260_pci1_mem_bs_tag, "pci1-mem", 497 ex_storage[bs], sizeof(ex_storage[bs])); 498 bs++; 499 500 #if 1 /* XXXXXX */ 501 /* 502 * Make sure PCI1 Memory is BAT mapped. 503 */ 504 if (GT_LowAddr_GET(datal) < GT_HighAddr_GET(datal)) 505 oea_iobat_add(ev64260_pci1_mem_bs_tag.pbs_base & SEGMENT_MASK, 506 BAT_BL_256M); 507 #endif 508 509 /* 510 * Make sure that I/O space start at 0. 511 */ 512 out32rb(gt_base + GT_PCI1_IO_Remap, 0); 513 514 datal = in32rb(gt_base + GT_PCI1_IO_Low_Decode); 515 datah = in32rb(gt_base + GT_PCI1_IO_High_Decode); 516 #if defined(GT_PCI1_IOBASE) 517 datal &= ~0xfff; 518 datal |= (GT_PCI1_IOBASE >> 20); 519 out32rb(gt_base + GT_PCI1_IO_Low_Decode, datal); 520 #endif 521 #if defined(GT_PCI1_IOSIZE) 522 datah &= ~0xfff; 523 datah |= (GT_PCI1_IOSIZE + GT_LowAddr_GET(datal) - 1) >> 20; 524 out32rb(gt_base + GT_PCI1_IO_High_Decode, datal); 525 #endif 526 ev64260_pci1_io_bs_tag.pbs_offset = GT_LowAddr_GET(datal); 527 ev64260_pci1_io_bs_tag.pbs_limit = GT_HighAddr_GET(datah) + 1 - 528 ev64260_pci1_io_bs_tag.pbs_offset; 529 530 error = bus_space_init(&ev64260_pci1_io_bs_tag, "pci1-ioport", 531 ex_storage[bs], sizeof(ex_storage[bs])); 532 bs++; 533 } 534 535 static inline void 536 gt_record_memory(int j, paddr_t start, paddr_t end, paddr_t endkernel) 537 { 538 physmemr[j].start = start; 539 physmemr[j].size = end - start; 540 if (start < endkernel) 541 start = endkernel; 542 availmemr[j].start = start; 543 availmemr[j].size = end - start; 544 } 545 546 static void 547 gt_find_memory(paddr_t endkernel) 548 { 549 paddr_t start = ~0, end = 0; 550 const struct gt_decode_info *di; 551 int i, j = 0, first = 1; 552 553 /* 554 * Round kernel end to a page boundary. 555 */ 556 for (i = 0; i < 4; i++) { 557 paddr_t nstart, nend; 558 559 di = &decode_regs[i]; 560 nstart = GT_LowAddr_GET(in32rb(gt_base + di->low_decode)); 561 nend = GT_HighAddr_GET(in32rb(gt_base + di->high_decode)) + 1; 562 if (nstart >= nend) 563 continue; 564 if (first) { 565 /* 566 * First entry? Just remember it. 567 */ 568 start = nstart; 569 end = nend; 570 first = 0; 571 } else if (nstart == end) { 572 /* 573 * Contiguous? Just update the end. 574 */ 575 end = nend; 576 } else { 577 /* 578 * Disjoint? record it. 579 */ 580 gt_record_memory(j, start, end, endkernel); 581 start = nstart; 582 end = nend; 583 j++; 584 } 585 } 586 gt_record_memory(j, start, end, endkernel); 587 } 588