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