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