brdsetup.c revision 1.4
1/* $NetBSD: brdsetup.c,v 1.4 2011/02/10 13:38:08 nisimura Exp $ */ 2 3/*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tohru Nishimura. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/param.h> 33 34#include <powerpc/oea/spr.h> 35 36#include <lib/libsa/stand.h> 37#include <lib/libsa/net.h> 38#include <lib/libkern/libkern.h> 39 40#include <machine/bootinfo.h> 41 42#include "globals.h" 43 44#define BRD_DECL(xxx) \ 45 void xxx ## setup(struct brdprop *); \ 46 void xxx ## brdfix(struct brdprop *); \ 47 void xxx ## pcifix(struct brdprop *); \ 48 void xxx ## reset(void) 49 50BRD_DECL(mot); 51BRD_DECL(enc); 52BRD_DECL(kuro); 53BRD_DECL(syno); 54BRD_DECL(qnap); 55BRD_DECL(iomega); 56BRD_DECL(dlink); 57 58static struct brdprop brdlist[] = { 59 { 60 "sandpoint", 61 "Sandpoint X3", 62 BRD_SANDPOINTX3, 63 0, 64 "com", 0x3f8, 115200, 65 motsetup, motbrdfix, motpcifix }, 66 { 67 "encpp1", 68 "EnCore PP1", 69 BRD_ENCOREPP1, 70 0, 71 "com", 0x3f8, 115200, 72 encsetup, encbrdfix, encpcifix }, 73 { 74 "kurobox", 75 "KuroBox", 76 BRD_KUROBOX, 77 32768000, 78 "eumb", 0x4600, 57600, 79 kurosetup, kurobrdfix, kuropcifix }, 80 { 81 "synology", 82 "Synology DS", 83 BRD_SYNOLOGY, 84 33164691, /* from Synology/Linux source */ 85 /* 33168000, XXX better precision? */ 86 "eumb", 0x4500, 115200, 87 synosetup, synobrdfix, synopcifix, synoreset }, 88 { 89 "qnap", 90 "QNAP TS-101", 91 BRD_QNAPTS101, 92 0, 93 "eumb", 0x4500, 115200, 94 NULL, NULL, qnappcifix }, 95 { 96 "iomega", 97 "IOMEGA StorCenter", 98 BRD_STORCENTER, 99 0, 100 "eumb", 0x4500, 115200, 101 NULL, iomegabrdfix, iomegapcifix }, 102 { 103 "dlink", 104 "D-Link DSM-G600", 105 BRD_DLINKDSM, 106 0, 107 "eumb", 0x4500, 9600, 108 NULL, dlinkbrdfix, dlinkpcifix }, 109 { 110 "unknown", 111 "Unknown board", 112 BRD_UNKNOWN, 113 0, 114 "eumb", 0x4500, 115200, 115 NULL, NULL, NULL }, /* must be the last */ 116}; 117 118static struct brdprop *brdprop; 119static uint32_t ticks_per_sec, ns_per_tick; 120 121static void brdfixup(void); 122static void setup(void); 123static inline uint32_t cputype(void); 124static inline u_quad_t mftb(void); 125static void init_uart(unsigned, unsigned, uint8_t); 126static void send_sat(char *); 127 128const unsigned dcache_line_size = 32; /* 32B linesize */ 129const unsigned dcache_range_size = 4 * 1024; /* 16KB / 4-way */ 130 131unsigned uart1base; /* console */ 132unsigned uart2base; /* optional satellite processor */ 133#define THR 0 134#define DLB 0 135#define DMB 1 136#define IER 1 137#define FCR 2 138#define LCR 3 139#define LCR_DLAB 0x80 140#define LCR_PEVEN 0x18 141#define LCR_PNONE 0x00 142#define LCR_8BITS 0x03 143#define MCR 4 144#define MCR_RTS 0x02 145#define MCR_DTR 0x01 146#define LSR 5 147#define LSR_THRE 0x20 148#define DCR 0x11 149#define UART_READ(base, r) *(volatile char *)(base + (r)) 150#define UART_WRITE(base, r, v) *(volatile char *)(base + (r)) = (v) 151 152void brdsetup(void); /* called by entry.S */ 153 154void 155brdsetup(void) 156{ 157 static uint8_t pci_to_memclk[] = { 158 30, 30, 10, 10, 20, 10, 10, 10, 159 10, 20, 20, 15, 20, 15, 20, 30, 160 30, 40, 15, 40, 20, 25, 20, 40, 161 25, 20, 10, 20, 15, 15, 20, 00 162 }; 163 static uint8_t mem_to_cpuclk[] = { 164 25, 30, 45, 20, 20, 00, 10, 30, 165 30, 20, 45, 30, 25, 35, 30, 35, 166 20, 25, 20, 30, 35, 40, 40, 20, 167 30, 25, 40, 30, 30, 25, 35, 00 168 }; 169 char *consname; 170 int consport; 171 uint32_t extclk; 172 unsigned pchb, pcib, val; 173 extern struct btinfo_memory bi_mem; 174 extern struct btinfo_console bi_cons; 175 extern struct btinfo_clock bi_clk; 176 extern struct btinfo_prodfamily bi_fam; 177 178 /* 179 * CHRP specification "Map-B" BAT012 layout 180 * BAT0 0000-0000 (256MB) SDRAM 181 * BAT1 8000-0000 (256MB) PCI mem space 182 * BAT2 fc00-0000 (64MB) EUMB, PCI I/O space, misc devs, flash 183 * 184 * EUMBBAR is at fc00-0000. 185 */ 186 pchb = pcimaketag(0, 0, 0); 187 pcicfgwrite(pchb, 0x78, 0xfc000000); 188 189 brdtype = BRD_UNKNOWN; 190 extclk = EXT_CLK_FREQ; /* usually 33MHz */ 191 busclock = 0; 192 193 if (pcifinddev(0x10ad, 0x0565, &pcib) == 0) { 194 brdtype = BRD_SANDPOINTX3; 195 } 196 else if (pcifinddev(0x1106, 0x0686, &pcib) == 0) { 197 brdtype = BRD_ENCOREPP1; 198 } 199 else if ((pcicfgread(pcimaketag(0, 11, 0), PCI_CLASS_REG) >> 16) == 200 PCI_CLASS_ETH) { 201 /* tlp (ADMtek AN985) or re (RealTek 8169S) at dev 11 */ 202 brdtype = BRD_KUROBOX; 203 } 204 else if (PCI_VENDOR(pcicfgread(pcimaketag(0, 15, 0), PCI_ID_REG)) == 205 0x11ab) { /* PCI_VENDOR_MARVELL */ 206 brdtype = BRD_SYNOLOGY; 207 } 208 else if (PCI_VENDOR(pcicfgread(pcimaketag(0, 15, 0), PCI_ID_REG)) == 209 0x8086) { /* PCI_VENDOR_INTEL */ 210 brdtype = BRD_QNAPTS101; 211 } 212 else if (PCI_VENDOR(pcicfgread(pcimaketag(0, 13, 0), PCI_ID_REG)) == 213 0x1106) { /* PCI_VENDOR_VIA */ 214 brdtype = BRD_STORCENTER; 215 } 216 else if (PCI_VENDOR(pcicfgread(pcimaketag(0, 16, 0), PCI_ID_REG)) == 217 0x1191) { /* PCI_VENDOR_ACARD */ 218 brdtype = BRD_DLINKDSM; 219 } 220 221 brdprop = brd_lookup(brdtype); 222 223 /* brd dependent adjustments */ 224 setup(); 225 226 /* determine clock frequencies */ 227 if (brdprop->extclk != 0) 228 extclk = brdprop->extclk; 229 if (busclock == 0) { 230 if (cputype() == MPC8245) { 231 /* PLL_CFG from PCI host bridge register 0xe2 */ 232 val = pcicfgread(pchb, 0xe0); 233 busclock = (extclk * 234 pci_to_memclk[(val >> 19) & 0x1f] + 10) / 10; 235 /* PLLRATIO from HID1 */ 236 __asm ("mfspr %0,1009" : "=r"(val)); 237 cpuclock = ((uint64_t)busclock * 238 mem_to_cpuclk[val >> 27] + 10) / 10; 239 } else 240 busclock = 100000000; /* 100MHz bus clock default */ 241 } 242 ticks_per_sec = busclock >> 2; 243 ns_per_tick = 1000000000 / ticks_per_sec; 244 245 /* now prepare serial console */ 246 consname = brdprop->consname; 247 consport = brdprop->consport; 248 if (strcmp(consname, "eumb") == 0) { 249 uart1base = 0xfc000000 + consport; /* 0x4500, 0x4600 */ 250 UART_WRITE(uart1base, DCR, 0x01); /* enable DUART mode */ 251 uart2base = uart1base ^ 0x0300; 252 } else 253 uart1base = 0xfe000000 + consport; /* 0x3f8, 0x2f8 */ 254 255 /* more brd adjustments */ 256 brdfixup(); 257 258 bi_mem.memsize = mpc107memsize(); 259 snprintf(bi_cons.devname, sizeof(bi_cons.devname), consname); 260 bi_cons.addr = consport; 261 bi_cons.speed = brdprop->consspeed; 262 bi_clk.ticks_per_sec = ticks_per_sec; 263 snprintf(bi_fam.name, sizeof(bi_fam.name), brdprop->family); 264} 265 266struct brdprop * 267brd_lookup(int brd) 268{ 269 u_int i; 270 271 for (i = 0; i < sizeof(brdlist)/sizeof(brdlist[0]); i++) { 272 if (brdlist[i].brdtype == brd) 273 return &brdlist[i]; 274 } 275 return &brdlist[i - 1]; 276} 277 278static void 279setup() 280{ 281 282 if (brdprop->setup == NULL) 283 return; 284 (*brdprop->setup)(brdprop); 285} 286 287static void 288brdfixup() 289{ 290 291 if (brdprop->brdfix == NULL) 292 return; 293 (*brdprop->brdfix)(brdprop); 294} 295 296void 297pcifixup() 298{ 299 300 if (brdprop->pcifix == NULL) 301 return; 302 (*brdprop->pcifix)(brdprop); 303} 304 305void 306encsetup(struct brdprop *brd) 307{ 308 309#ifdef COSNAME 310 brd->consname = CONSNAME; 311#endif 312#ifdef CONSPORT 313 brd->consport = CONSPORT; 314#endif 315#ifdef CONSSPEED 316 brd->consspeed = CONSSPEED; 317#endif 318} 319 320void 321encbrdfix(struct brdprop *brd) 322{ 323 unsigned ac97, ide, pcib, pmgt, usb12, umot4, val; 324 325/* 326 * VIA82C686B Southbridge 327 * 0.22.0 1106.0686 PCI-ISA bridge 328 * 0.22.1 1106.0571 IDE (viaide) 329 * 0.22.2 1106.3038 USB 0/1 (uhci) 330 * 0.22.3 1106.3038 USB 2/3 (uhci) 331 * 0.22.4 1106.3057 power management 332 * 0.22.5 1106.3058 AC97 (auvia) 333 */ 334 pcib = pcimaketag(0, 22, 0); 335 ide = pcimaketag(0, 22, 1); 336 usb12 = pcimaketag(0, 22, 2); 337 umot4 = pcimaketag(0, 22, 3); 338 pmgt = pcimaketag(0, 22, 4); 339 ac97 = pcimaketag(0, 22, 5); 340 341#define CFG(i,v) do { \ 342 *(volatile unsigned char *)(0xfe000000 + 0x3f0) = (i); \ 343 *(volatile unsigned char *)(0xfe000000 + 0x3f1) = (v); \ 344 } while (0) 345 val = pcicfgread(pcib, 0x84); 346 val |= (02 << 8); 347 pcicfgwrite(pcib, 0x84, val); 348 CFG(0xe2, 0x0f); /* use COM1/2, don't use FDC/LPT */ 349 val = pcicfgread(pcib, 0x84); 350 val &= ~(02 << 8); 351 pcicfgwrite(pcib, 0x84, val); 352 353 /* route pin C to i8259 IRQ 5, pin D to 11 */ 354 val = pcicfgread(pcib, 0x54); 355 val = (val & 0xff) | 0xb0500000; /* Dx CB Ax xS */ 356 pcicfgwrite(pcib, 0x54, val); 357 358 /* enable EISA ELCR1 (0x4d0) and ELCR2 (0x4d1) */ 359 val = pcicfgread(pcib, 0x44); 360 val = val | 0x20000000; 361 pcicfgwrite(pcib, 0x44, val); 362 363 /* select level trigger for IRQ 5/11 at ELCR1/2 */ 364 *(volatile uint8_t *)0xfe0004d0 = 0x20; /* bit 5 */ 365 *(volatile uint8_t *)0xfe0004d1 = 0x08; /* bit 11 */ 366 367 /* USB and AC97 are hardwired with pin D and C */ 368 val = pcicfgread(usb12, 0x3c) &~ 0xff; 369 val |= 11; 370 pcicfgwrite(usb12, 0x3c, val); 371 val = pcicfgread(umot4, 0x3c) &~ 0xff; 372 val |= 11; 373 pcicfgwrite(umot4, 0x3c, val); 374 val = pcicfgread(ac97, 0x3c) &~ 0xff; 375 val |= 5; 376 pcicfgwrite(ac97, 0x3c, val); 377} 378 379void 380motsetup(struct brdprop *brd) 381{ 382 383#ifdef COSNAME 384 brd->consname = CONSNAME; 385#endif 386#ifdef CONSPORT 387 brd->consport = CONSPORT; 388#endif 389#ifdef CONSSPEED 390 brd->consspeed = CONSSPEED; 391#endif 392} 393 394void 395motbrdfix(struct brdprop *brd) 396{ 397 398/* 399 * WinBond/Symphony Lab 83C553 with PC87308 "SuperIO" 400 * 401 * 0.11.0 10ad.0565 PCI-ISA bridge 402 * 0.11.1 10ad.0105 IDE (slide) 403 */ 404} 405 406void 407motpcifix(struct brdprop *brd) 408{ 409 unsigned ide, net, pcib, steer, val; 410 int line; 411 412 pcib = pcimaketag(0, 11, 0); 413 ide = pcimaketag(0, 11, 1); 414 net = pcimaketag(0, 15, 0); 415 416 /* 417 * //// WinBond PIRQ //// 418 * 0x40 - bit 5 (0x20) indicates PIRQ presense 419 * 0x60 - PIRQ interrupt routing steer 420 */ 421 if (pcicfgread(pcib, 0x40) & 0x20) { 422 steer = pcicfgread(pcib, 0x60); 423 if ((steer & 0x80808080) == 0x80808080) 424 printf("PIRQ[0-3] disabled\n"); 425 else { 426 unsigned i, v = steer; 427 for (i = 0; i < 4; i++, v >>= 8) { 428 if ((v & 0x80) != 0 || (v & 0xf) == 0) 429 continue; 430 printf("PIRQ[%d]=%d\n", i, v & 0xf); 431 } 432 } 433 } 434#if 1 435 /* 436 * //// IDE fixup -- case A //// 437 * - "native PCI mode" (ide 0x09) 438 * - don't use ISA IRQ14/15 (pcib 0x43) 439 * - native IDE for both channels (ide 0x40) 440 * - LEGIRQ bit 11 steers interrupt to pin C (ide 0x40) 441 * - sign as PCI pin C line 11 (ide 0x3d/3c) 442 */ 443 /* ide: 0x09 - programming interface; 1000'SsPp */ 444 val = pcicfgread(ide, 0x08); 445 val &= 0xffff00ff; 446 pcicfgwrite(ide, 0x08, val | (0x8f << 8)); 447 448 /* pcib: 0x43 - IDE interrupt routing */ 449 val = pcicfgread(pcib, 0x40) & 0x00ffffff; 450 pcicfgwrite(pcib, 0x40, val); 451 452 /* pcib: 0x45/44 - PCI interrupt routing */ 453 val = pcicfgread(pcib, 0x44) & 0xffff0000; 454 pcicfgwrite(pcib, 0x44, val); 455 456 /* ide: 0x41/40 - IDE channel */ 457 val = pcicfgread(ide, 0x40) & 0xffff0000; 458 val |= (1 << 11) | 0x33; /* LEGIRQ turns on PCI interrupt */ 459 pcicfgwrite(ide, 0x40, val); 460 461 /* ide: 0x3d/3c - use PCI pin C/line 11 */ 462 val = pcicfgread(ide, 0x3c) & 0xffffff00; 463 val |= 11; /* pin designation is hardwired to pin A */ 464 pcicfgwrite(ide, 0x3c, val); 465#else 466 /* 467 * //// IDE fixup -- case B //// 468 * - "compatiblity mode" (ide 0x09) 469 * - IDE primary/secondary interrupt routing (pcib 0x43) 470 * - PCI interrupt routing (pcib 0x45/44) 471 * - no PCI pin/line assignment (ide 0x3d/3c) 472 */ 473 /* ide: 0x09 - programming interface; 1000'SsPp */ 474 val = pcicfgread(ide, 0x08); 475 val &= 0xffff00ff; 476 pcicfgwrite(ide, 0x08, val | (0x8a << 8)); 477 478 /* pcib: 0x43 - IDE interrupt routing */ 479 val = pcicfgread(pcib, 0x40) & 0x00ffffff; 480 pcicfgwrite(pcib, 0x40, val | (0xee << 24)); 481 482 /* ide: 0x45/44 - PCI interrupt routing */ 483 val = pcicfgread(ide, 0x44) & 0xffff0000; 484 pcicfgwrite(ide, 0x44, val); 485 486 /* ide: 0x3d/3c - turn off PCI pin/line */ 487 val = pcicfgread(ide, 0x3c) & 0xffff0000; 488 pcicfgwrite(ide, 0x3c, val); 489#endif 490 491 /* 492 * //// fxp fixup //// 493 * - use PCI pin A line 15 (fxp 0x3d/3c) 494 */ 495 val = pcicfgread(net, 0x3c) & 0xffff0000; 496 pcidecomposetag(net, NULL, &line, NULL); 497 val |= (('A' - '@') << 8) | line; 498 pcicfgwrite(net, 0x3c, val); 499} 500 501void 502encpcifix(struct brdprop *brd) 503{ 504 unsigned ide, irq, net, pcib, steer, val; 505 506#define STEER(v, b) (((v) & (b)) ? "edge" : "level") 507 pcib = pcimaketag(0, 22, 0); 508 ide = pcimaketag(0, 22, 1); 509 net = pcimaketag(0, 25, 0); 510 511 /* 512 * //// VIA PIRQ //// 513 * 0x57/56/55/54 - Dx CB Ax xS 514 */ 515 val = pcicfgread(pcib, 0x54); /* Dx CB Ax xs */ 516 steer = val & 0xf; 517 irq = (val >> 12) & 0xf; /* 15:12 */ 518 if (irq) { 519 printf("pin A -> irq %d, %s\n", 520 irq, STEER(steer, 0x1)); 521 } 522 irq = (val >> 16) & 0xf; /* 19:16 */ 523 if (irq) { 524 printf("pin B -> irq %d, %s\n", 525 irq, STEER(steer, 0x2)); 526 } 527 irq = (val >> 20) & 0xf; /* 23:20 */ 528 if (irq) { 529 printf("pin C -> irq %d, %s\n", 530 irq, STEER(steer, 0x4)); 531 } 532 irq = (val >> 28); /* 31:28 */ 533 if (irq) { 534 printf("pin D -> irq %d, %s\n", 535 irq, STEER(steer, 0x8)); 536 } 537#if 0 538 /* 539 * //// IDE fixup //// 540 * - "native mode" (ide 0x09) 541 * - use primary only (ide 0x40) 542 */ 543 /* ide: 0x09 - programming interface; 1000'SsPp */ 544 val = pcicfgread(ide, 0x08) & 0xffff00ff; 545 pcicfgwrite(ide, 0x08, val | (0x8f << 8)); 546 547 /* ide: 0x10-20 - leave them PCI memory space assigned */ 548 549 /* ide: 0x40 - use primary only */ 550 val = pcicfgread(ide, 0x40) &~ 03; 551 val |= 02; 552 pcicfgwrite(ide, 0x40, val); 553#else 554 /* 555 * //// IDE fixup //// 556 * - "compatiblity mode" (ide 0x09) 557 * - use primary only (ide 0x40) 558 * - remove PCI pin assignment (ide 0x3d) 559 */ 560 /* ide: 0x09 - programming interface; 1000'SsPp */ 561 val = pcicfgread(ide, 0x08) & 0xffff00ff; 562 val |= (0x8a << 8); 563 pcicfgwrite(ide, 0x08, val); 564 565 /* ide: 0x10-20 */ 566 /* 567 experiment shows writing ide: 0x09 changes these 568 register behaviour. The pcicfgwrite() above writes 569 0x8a at ide: 0x09 to make sure legacy IDE. Then 570 reading BAR0-3 is to return value 0s even though 571 pcisetup() has written range assignments. Value 572 overwrite makes no effect. Having 0x8f for native 573 PCIIDE doesn't change register values and brings no 574 weirdness. 575 */ 576 577 /* ide: 0x40 - use primary only */ 578 val = pcicfgread(ide, 0x40) &~ 03; 579 val |= 02; 580 pcicfgwrite(ide, 0x40, val); 581 582 /* ide: 0x3d/3c - turn off PCI pin */ 583 val = pcicfgread(ide, 0x3c) & 0xffff00ff; 584 pcicfgwrite(ide, 0x3c, val); 585#endif 586 /* 587 * //// USBx2, audio, and modem fixup //// 588 * - disable USB #0 and #1 (pcib 0x48 and 0x85) 589 * - disable AC97 audio and MC97 modem (pcib 0x85) 590 */ 591 592 /* pcib: 0x48 - disable USB #0 at function 2 */ 593 val = pcicfgread(pcib, 0x48); 594 pcicfgwrite(pcib, 0x48, val | 04); 595 596 /* pcib: 0x85 - disable USB #1 at function 3 */ 597 /* pcib: 0x85 - disable AC97/MC97 at function 5/6 */ 598 val = pcicfgread(pcib, 0x84); 599 pcicfgwrite(pcib, 0x84, val | 0x1c00); 600 601 /* 602 * //// fxp fixup //// 603 * - use PCI pin A line 25 (fxp 0x3d/3c) 604 */ 605 /* 0x3d/3c - PCI pin/line */ 606 val = pcicfgread(net, 0x3c) & 0xffff0000; 607 val |= (('A' - '@') << 8) | 25; 608 pcicfgwrite(net, 0x3c, val); 609} 610 611void 612kurosetup(struct brdprop *brd) 613{ 614 615 if (PCI_VENDOR(pcicfgread(pcimaketag(0, 11, 0), PCI_ID_REG)) == 0x10ec) 616 brd->extclk = 32768000; /* decr 2457600Hz */ 617 else 618 brd->extclk = 32521333; /* decr 2439100Hz */ 619} 620 621void 622kurobrdfix(struct brdprop *brd) 623{ 624 625 init_uart(uart2base, 9600, LCR_8BITS | LCR_PEVEN); 626 /* Stop Watchdog */ 627 send_sat("AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK"); 628} 629 630void 631kuropcifix(struct brdprop *brd) 632{ 633 unsigned dsk, net, usb, val; 634 635 net = pcimaketag(0, 11, 0); 636 val = pcicfgread(net, 0x3c) & 0xffffff00; 637 val |= 11; 638 pcicfgwrite(net, 0x3c, val); 639 640 dsk = pcimaketag(0, 12, 0); 641 val = pcicfgread(dsk, 0x3c) & 0xffffff00; 642 val |= 12; 643 pcicfgwrite(dsk, 0x3c, val); 644 645 usb = pcimaketag(0, 14, 0); 646 val = pcicfgread(usb, 0x3c) & 0xffffff00; 647 val |= 14; 648 pcicfgwrite(usb, 0x3c, val); 649 650 usb = pcimaketag(0, 14, 1); 651 val = pcicfgread(usb, 0x3c) & 0xffffff00; 652 val |= 14; 653 pcicfgwrite(usb, 0x3c, val); 654 655 usb = pcimaketag(0, 14, 2); 656 val = pcicfgread(usb, 0x3c) & 0xffffff00; 657 val |= 14; 658 pcicfgwrite(usb, 0x3c, val); 659} 660 661void 662synosetup(struct brdprop *brd) 663{ 664 665 /* nothing */ 666} 667 668void 669synobrdfix(struct brdprop *brd) 670{ 671 672 init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE); 673 /* beep, power LED on, status LED off */ 674 send_sat("247"); 675} 676 677void 678synopcifix(struct brdprop *brd) 679{ 680 unsigned dsk, net, usb, val; 681 682 dsk = pcimaketag(0, 13, 0); 683 val = pcicfgread(dsk, 0x3c) & 0xffffff00; 684 val |= 13; 685 pcicfgwrite(dsk, 0x3c, val); 686 687 usb = pcimaketag(0, 14, 0); 688 val = pcicfgread(usb, 0x3c) & 0xffffff00; 689 val |= 14; 690 pcicfgwrite(usb, 0x3c, val); 691 692 usb = pcimaketag(0, 14, 1); 693 val = pcicfgread(usb, 0x3c) & 0xffffff00; 694 val |= 14; 695 pcicfgwrite(usb, 0x3c, val); 696 697 usb = pcimaketag(0, 14, 2); 698 val = pcicfgread(usb, 0x3c) & 0xffffff00; 699 val |= 14; 700 pcicfgwrite(usb, 0x3c, val); 701 702 net = pcimaketag(0, 15, 0); 703 val = pcicfgread(net, 0x3c) & 0xffffff00; 704 val |= 15; 705 pcicfgwrite(net, 0x3c, val); 706} 707 708void 709synoreset() 710{ 711 712 send_sat("C"); 713 /*NOTRECHED*/ 714} 715 716void 717qnappcifix(struct brdprop *brd) 718{ 719 unsigned dsk, net, usb, val; 720 721 dsk = pcimaketag(0, 13, 0); 722 val = pcicfgread(dsk, 0x3c) & 0xffffff00; 723 val |= 13; 724 pcicfgwrite(dsk, 0x3c, val); 725 726 usb = pcimaketag(0, 14, 0); 727 val = pcicfgread(usb, 0x3c) & 0xffffff00; 728 val |= 14; 729 pcicfgwrite(usb, 0x3c, val); 730 731 usb = pcimaketag(0, 14, 1); 732 val = pcicfgread(usb, 0x3c) & 0xffffff00; 733 val |= 14; 734 pcicfgwrite(usb, 0x3c, val); 735 736 usb = pcimaketag(0, 14, 2); 737 val = pcicfgread(usb, 0x3c) & 0xffffff00; 738 val |= 14; 739 pcicfgwrite(usb, 0x3c, val); 740 741 net = pcimaketag(0, 15, 0); 742 val = pcicfgread(net, 0x3c) & 0xffffff00; 743 val |= 15; 744 pcicfgwrite(net, 0x3c, val); 745} 746 747void 748iomegabrdfix(struct brdprop *brd) 749{ 750 751 init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE); 752} 753 754void 755iomegapcifix(struct brdprop *brd) 756{ 757 unsigned dsk, net, usb, val; 758 759 dsk = pcimaketag(0, 13, 0); 760 val = pcicfgread(dsk, 0x3c) & 0xffffff00; 761 val |= 13; 762 pcicfgwrite(dsk, 0x3c, val); 763 764 usb = pcimaketag(0, 14, 0); 765 val = pcicfgread(usb, 0x3c) & 0xffffff00; 766 val |= 14; 767 pcicfgwrite(usb, 0x3c, val); 768 769 usb = pcimaketag(0, 14, 1); 770 val = pcicfgread(usb, 0x3c) & 0xffffff00; 771 val |= 14; 772 pcicfgwrite(usb, 0x3c, val); 773 774 usb = pcimaketag(0, 14, 2); 775 val = pcicfgread(usb, 0x3c) & 0xffffff00; 776 val |= 14; 777 pcicfgwrite(usb, 0x3c, val); 778 779 net = pcimaketag(0, 15, 0); 780 val = pcicfgread(net, 0x3c) & 0xffffff00; 781 val |= 15; 782 pcicfgwrite(net, 0x3c, val); 783} 784 785void 786dlinkbrdfix(struct brdprop *brd) 787{ 788 789 init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE); 790} 791 792void 793dlinkpcifix(struct brdprop *brd) 794{ 795 unsigned usb, net, dsk, val; 796 797 usb = pcimaketag(0, 14, 0); 798 val = pcicfgread(usb, 0x3c) & 0xffffff00; 799 val |= 14; 800 pcicfgwrite(usb, 0x3c, val); 801 802 usb = pcimaketag(0, 14, 1); 803 val = pcicfgread(usb, 0x3c) & 0xffffff00; 804 val |= 14; 805 pcicfgwrite(usb, 0x3c, val); 806 807 usb = pcimaketag(0, 14, 2); 808 val = pcicfgread(usb, 0x3c) & 0xffffff00; 809 val |= 14; 810 pcicfgwrite(usb, 0x3c, val); 811 812 net = pcimaketag(0, 15, 0); 813 val = pcicfgread(net, 0x3c) & 0xffffff00; 814 val |= 15; 815 pcicfgwrite(net, 0x3c, val); 816 817 dsk = pcimaketag(0, 16, 0); 818 val = pcicfgread(dsk, 0x3c) & 0xffffff00; 819 val |= 16; 820 pcicfgwrite(dsk, 0x3c, val); 821} 822 823void 824_rtt(void) 825{ 826 827 if (brdprop->reset != NULL) 828 (*brdprop->reset)(); 829 else 830 run(0, 0, 0, 0, (void *)0xFFF00100); /* reset entry */ 831 /*NOTREACHED*/ 832} 833 834satime_t 835getsecs(void) 836{ 837 u_quad_t tb = mftb(); 838 839 return (tb / ticks_per_sec); 840} 841 842/* 843 * Wait for about n microseconds (at least!). 844 */ 845void 846delay(u_int n) 847{ 848 u_quad_t tb; 849 u_long scratch, tbh, tbl; 850 851 tb = mftb(); 852 tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick; 853 tbh = tb >> 32; 854 tbl = tb; 855 asm volatile ("1: mftbu %0; cmpw %0,%1; blt 1b; bgt 2f; mftb %0; cmpw 0, %0,%2; blt 1b; 2:" : "=&r"(scratch) : "r"(tbh), "r"(tbl)); 856} 857 858void 859_wb(uint32_t adr, uint32_t siz) 860{ 861 uint32_t bnd; 862 863 asm volatile("eieio"); 864 for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) 865 asm volatile ("dcbst 0,%0" :: "r"(adr)); 866 asm volatile ("sync"); 867} 868 869void 870_wbinv(uint32_t adr, uint32_t siz) 871{ 872 uint32_t bnd; 873 874 asm volatile("eieio"); 875 for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) 876 asm volatile ("dcbf 0,%0" :: "r"(adr)); 877 asm volatile ("sync"); 878} 879 880void 881_inv(uint32_t adr, uint32_t siz) 882{ 883 uint32_t bnd, off; 884 885 off = adr & (dcache_line_size - 1); 886 adr -= off; 887 siz += off; 888 asm volatile ("eieio"); 889 if (off != 0) { 890 /* wbinv() leading unaligned dcache line */ 891 asm volatile ("dcbf 0,%0" :: "r"(adr)); 892 if (siz < dcache_line_size) 893 goto done; 894 adr += dcache_line_size; 895 siz -= dcache_line_size; 896 } 897 bnd = adr + siz; 898 off = bnd & (dcache_line_size - 1); 899 if (off != 0) { 900 /* wbinv() trailing unaligned dcache line */ 901 asm volatile ("dcbf 0,%0" :: "r"(bnd)); /* it's OK */ 902 if (siz < dcache_line_size) 903 goto done; 904 siz -= off; 905 } 906 for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) { 907 /* inv() intermediate dcache lines if ever */ 908 asm volatile ("dcbi 0,%0" :: "r"(adr)); 909 } 910 done: 911 asm volatile ("sync"); 912} 913 914static inline uint32_t 915cputype(void) 916{ 917 uint32_t pvr; 918 919 __asm volatile ("mfpvr %0" : "=r"(pvr)); 920 return pvr >> 16; 921} 922 923static inline u_quad_t 924mftb(void) 925{ 926 u_long scratch; 927 u_quad_t tb; 928 929 asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw %0,%1; bne 1b" 930 : "=r"(tb), "=r"(scratch)); 931 return (tb); 932} 933 934static void 935init_uart(unsigned base, unsigned speed, uint8_t lcr) 936{ 937 unsigned div; 938 939 div = busclock / speed / 16; 940 UART_WRITE(base, LCR, 0x80); /* turn on DLAB bit */ 941 UART_WRITE(base, FCR, 0x00); 942 UART_WRITE(base, DMB, div >> 8); /* set speed */ 943 UART_WRITE(base, DLB, div & 0xff); 944 UART_WRITE(base, LCR, lcr); 945 UART_WRITE(base, FCR, 0x07); /* FIFO on, TXRX FIFO reset */ 946 UART_WRITE(base, IER, 0x00); /* make sure INT disabled */ 947} 948 949/* talk to satellite processor */ 950static void 951send_sat(char *msg) 952{ 953 unsigned savedbase; 954 955 savedbase = uart1base; 956 uart1base = uart2base; 957 while (*msg) 958 putchar(*msg++); 959 uart1base = savedbase; 960} 961 962void 963putchar(int c) 964{ 965 unsigned timo, lsr; 966 967 if (c == '\n') 968 putchar('\r'); 969 970 timo = 0x00100000; 971 do { 972 lsr = UART_READ(uart1base, LSR); 973 } while (timo-- > 0 && (lsr & LSR_THRE) == 0); 974 if (timo > 0) 975 UART_WRITE(uart1base, THR, c); 976} 977 978unsigned 979mpc107memsize() 980{ 981 unsigned bankn, end, n, tag, val; 982 983 tag = pcimaketag(0, 0, 0); 984 985 if (brdtype == BRD_ENCOREPP1) { 986 /* the brd's PPCBOOT looks to have erroneous values */ 987 unsigned tbl[] = { 988#define MPC106_MEMSTARTADDR1 0x80 989#define MPC106_EXTMEMSTARTADDR1 0x88 990#define MPC106_MEMENDADDR1 0x90 991#define MPC106_EXTMEMENDADDR1 0x98 992#define MPC106_MEMEN 0xa0 993#define BK0_S 0x00000000 994#define BK0_E (128 << 20) - 1 995#define BK1_S 0x3ff00000 996#define BK1_E 0x3fffffff 997#define BK2_S 0x3ff00000 998#define BK2_E 0x3fffffff 999#define BK3_S 0x3ff00000 1000#define BK3_E 0x3fffffff 1001#define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s)) 1002#define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s)) 1003#define SAR_MASK 0x0ff00000 1004#define SAR_SHIFT 20 1005#define EAR_MASK 0x30000000 1006#define EAR_SHIFT 28 1007 AR(BK0_S, 0) | AR(BK1_S, 8) | AR(BK2_S, 16) | AR(BK3_S, 24), 1008 XR(BK0_S, 0) | XR(BK1_S, 8) | XR(BK2_S, 16) | XR(BK3_S, 24), 1009 AR(BK0_E, 0) | AR(BK1_E, 8) | AR(BK2_E, 16) | AR(BK3_E, 24), 1010 XR(BK0_E, 0) | XR(BK1_E, 8) | XR(BK2_E, 16) | XR(BK3_E, 24), 1011 }; 1012 tag = pcimaketag(0, 0, 0); 1013 pcicfgwrite(tag, MPC106_MEMSTARTADDR1, tbl[0]); 1014 pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, tbl[1]); 1015 pcicfgwrite(tag, MPC106_MEMENDADDR1, tbl[2]); 1016 pcicfgwrite(tag, MPC106_EXTMEMENDADDR1, tbl[3]); 1017 pcicfgwrite(tag, MPC106_MEMEN, 1); 1018 } 1019 1020 bankn = 0; 1021 val = pcicfgread(tag, MPC106_MEMEN); 1022 for (n = 0; n < 4; n++) { 1023 if ((val & (1U << n)) == 0) 1024 break; 1025 bankn = n; 1026 } 1027 bankn = bankn * 8; 1028 1029 val = pcicfgread(tag, MPC106_EXTMEMENDADDR1); 1030 end = ((val >> bankn) & 0x03) << 28; 1031 val = pcicfgread(tag, MPC106_MEMENDADDR1); 1032 end |= ((val >> bankn) & 0xff) << 20; 1033 end |= 0xfffff; 1034 1035 return (end + 1); /* assume the end address matches total amount */ 1036} 1037 1038struct fis_dir_entry { 1039 char name[16]; 1040 uint32_t startaddr; 1041 uint32_t loadaddr; 1042 uint32_t flashsize; 1043 uint32_t entryaddr; 1044 uint32_t filesize; 1045 char pad[256 - (16 + 5 * sizeof(uint32_t))]; 1046}; 1047 1048#define FIS_LOWER_LIMIT 0xfff00000 1049 1050/* 1051 * Look for a Redboot-style Flash Image System FIS-directory and 1052 * return a pointer to the start address of the requested file. 1053 */ 1054static void * 1055redboot_fis_lookup(const char *filename) 1056{ 1057 static const char FISdirname[16] = { 1058 'F', 'I', 'S', ' ', 1059 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0 1060 }; 1061 struct fis_dir_entry *dir; 1062 1063 /* 1064 * The FIS directory is usually in the last sector of the flash. 1065 * But we do not know the sector size (erase size), so start 1066 * at 0xffffff00 and scan backwards in steps of the FIS directory 1067 * entry size (0x100). 1068 */ 1069 for (dir = (struct fis_dir_entry *)0xffffff00; 1070 (uint32_t)dir >= FIS_LOWER_LIMIT; dir--) 1071 if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0) 1072 break; 1073 if ((uint32_t)dir < FIS_LOWER_LIMIT) { 1074 printf("No FIS directory found!\n"); 1075 return NULL; 1076 } 1077 1078 /* Now find filename by scanning the directory from beginning. */ 1079 dir = (struct fis_dir_entry *)dir->startaddr; 1080 while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) { 1081 if (strcmp(dir->name, filename) == 0) 1082 return (void *)dir->startaddr; /* found */ 1083 dir++; 1084 } 1085 printf("\"%s\" not found in FIS directory!\n", filename); 1086 return NULL; 1087} 1088 1089/* 1090 * For cost saving reasons some NAS boxes are missing the ROM for the 1091 * NIC's ethernet address and keep it in their Flash memory. 1092 */ 1093void 1094read_mac_from_flash(uint8_t *mac) 1095{ 1096 uint8_t *p; 1097 1098 if (brdtype == BRD_SYNOLOGY) { 1099 p = redboot_fis_lookup("vendor"); 1100 if (p != NULL) { 1101 memcpy(mac, p, 6); 1102 return; 1103 } 1104 } else 1105 printf("Warning: This board has no known method defined " 1106 "to determine its MAC address!\n"); 1107 1108 /* set to 00:00:00:00:00:00 in case of error */ 1109 memset(mac, 0, 6); 1110} 1111